Helper classes in Java ActionPack: Design Decisions

Posted by Berin Loritsch Wed, 31 Oct 2007 17:49:00 GMT

One of the nice features of Ruby on Rails is the ability to mix in helper classes with your controller. This works seamlessly because of the design of the Ruby language. When you try the same approach in Java it’s just plain impossible. For one thing, Java has no way to mix things in properly. You could have a setter/getter for the helper class, but you run into type issues if you want to do it automatically. Either you have to explicitly cast all helpers when you use them, or you have to rely on Java’s broken generics approach. It’s twofold the problem because the controller needs to access the helper, and the helper also needs to access the controller.

Now, Ruby on Rails uses the same helper class mixed in to the controller as well as into the view. At this stage in the game, I think that’s pretty much a pipe dream. I mean, it’s possible to add the helper class instance to a “helper” request attribute, but JSTL and JSP EL doesn’t allow you to call methods with parameters so it’s kind of a moot point. I’d like to fix these limitations in an Java ActiveView project, but that’s in the future.

Without worrying about all the niceties of the way I would prefer to work, I still need to work within the constructs and design mindset of Java. Sometimes the straitjacket forces you to be creative, but I can’t think of any clean way that will work without hijacking the compiler. That’s not really an option because it creates the need for tools just to work with the framework. It’s highly invasive, and it would make me less likely to use the tool—and I’m the one writing it.

The short term solution is to make all the protected support methods in the controller public. That allows users to pass the controller to the helper class, and the helper can invoke whatever methods it needs. That also means that I need to make the “layout” property have setters and getters. Perhaps a medium term solution would be to create a Request Package that included the request object, session object, response object, and all the helper methods to manipulate them (like “redirectToAction” and “sendMessage”). The controller would either use this object directly, or the same methods would simply delegate to the request package object. That object would then be used for both the helper and the controller. That will allow you to have a series of static methods that consume the request package or the controller directly. It’s up to you how you want to do it.

I haven’t really finished my decision process, but I’m all for any ideas that any of you may want to throw my way.

Controller Mixins? 2

Posted by Berin Loritsch Wed, 12 Sep 2007 12:18:00 GMT

One of the things I’m wanting to solve (in a simple and elegant manner) is the problem of caching. Essentially I want to introduce an interface that you can place on things that would be put in a request or session attribute so that I can determine the cacheability of the page dynamically. It would be easy enough to introduce a base class that takes care of this for me. The problem is that not every controller needs to have caching, and some controllers need to force no caching within the same application. Not to mention, if we want to add a set of actions to an existing controller like the Ruby on Rails scaffolding mixin we would be required to either have a multiplicity of base classes or we would need a mixin functionality like Ruby.

Now, the cool thing with ActionPack is that we are already calling methods introspectively on a class, so what could be difficult about calling methods on another controller that is “mixed in” to your controller? That allows you to manage functionality chunks effectively. The mixin controllers don’t have to be (and really shouldn’t be) in the same package as the rest of your controllers. The only issue comes up where a controller has the same action of a mixed-in controller. The action has to be simple and predictable every time. My current thinking is to provide the same action as inheritance. I.e. the new action would override the old action. The only issue comes with calling super.actionName() within the action. How do we capture that? The only way I can think of is that we provide one method to handle the delegation if it is called. For example yield() would tell the controller to look in it’s mixins for the corresponding action and call it.

The idea is pretty cool, and the ability to snap in aspects of functionality into your web application is truly useful. It’s a truer version of separation of concerns without the intrusiveness and lack of clarity as the more traditional aspect oriented programming (AOP) efforts. However, it does introduce a certain intellectual complexity. We have to make it really obvious to developers that mixins are being used, and we have to use a design principle that Java developers are used to. That’s why I intend to imitate the functionality of inheritance as best I can. Mixing in multiple controllers also requires predictability. The order that a developer mixes in controllers must be respected. If two controllers don’t play nice together, the developer needs to have the ability to override the order that the actions are called.

I’m balancing the payoff for the complexity involved. I’m also thinking about how to implement the thing, to keep things as transparent as possible to users of the ActionPack framework, yet apparent as possible to developers of the ActionPack framework. The one thing I haven’t touched is what to do with views associated with the mixins. That’s going to be a big issue to work out later. First I want to do logic only mixins. Yet another question is when are mixins allowed to be added/created? It might be terribly useful to add mixins based on user parameters. For example, if the application supports users from several companies, and they want navigation cues specific to their company then adding in the mixin specific to that company would be something done in a filter. If we provide no limitations, and only require that the mixin is applied before it is used, that might also be an option.

I’m thinking that the mixin approach is definitely going to be used, the question is really how to make it easy to understand .

Annotations: The Language Shoehorn?

Posted by Berin Loritsch Fri, 07 Sep 2007 13:07:00 GMT

A while back, before they had such a wide variety of shoe sizes to fit everybody’s foot we had this tool called a shoehorn. The shoehorn was there to help force your foot into a shoe that no longer fit. Well, it’s purpose was to keep the heel of the shoe from collapsing—but back in the day we used it to get a little more life out of a shoe that was too small. Buying a new pair of shoes was out of the question, because it was a choice between spending the $30 on shoes or some other need that we had. Times have changed, and so has my budget.

Background

Software languages have undergone many different fundamental shifts in thought over the years as well. Originally we had machine language and its symbolic cousin Assembly Language. Originally they had little structure and GOTOs (AKA JMP instructions) were written to specific addresses. Some natural evolutions happened as processors became more complex and subroutines were born, enabling some of the more Calculus like breakdown of applications. The first thought shift was Structured Programming which replaced hard addresses with symbols and registers with variables, and enabled an arbitrary number of variables—despite the limitations of the processor underneath. Then came Procedural Programming with C and its collection of similar languages. You’d think that Object Oriented Programming came next, but that was just one of several other shifts in thought. You also had declarative languages, logic languages, etc. For a longer breakdown you can visit Wikipedia’s Programming paradigm page. Each programming train of thought lends itself to a particular set of problems.

The ultimate sophistication is simplicity. Leonardo da Vinci

There are many aspects to simplicity, and it’s easy for me to throw this term around and add the disclaimer about how it’s easier said than done. Instead, let’s explore what makes software simple. What goes into this word simplicity that I keep harping on?

  1. Economy of concepts. There should be no more than one or two fundamental design principles that are used consistently, and without exception. If there are two principles, the choice between them also has to be consistently applied and clear when to use which principle.
  2. Consistency. As soon as you add one exception to any rule, you’ve just made it a lot more difficult to understand. For you math happy folks think of the complexity in terms of Re+1 where R is the number of rules and e is the number of exceptions (in total). Smaller numbers are more simple and easier to understand. For example, if you have 9 rules and rule 1 has 2 exceptions and rule 3 has 4 exceptions the complexity is 96+1 or 4,782,969. That’s bad.
  3. Predictability. Every action that you can make has to have a clear and predictable outcome. To understand the impact of unpredictability, treat the math for predictability like the math for consistency. For everything that can go wrong, you’ve just made the system that much harder to comprehend.
  4. Self evident. Based on the consistently applied principles and the predictability of actions, the course of action for the user to take should be self evident. In short, once you’ve learned how things work you shouldn’t need anyone to hold your hand when you have to make a change.

Now you get an idea of what I mean by simplicity, and how it is actually hard to pull off for anything but simplistic systems. I mean if you only have two rules and two exceptions you still have a relatively simple system. Of course, once you start adding more rules and actions the complexity increases exponentially.

Annotations Are Mixing Concepts

I’ll be the first to say that Annotations are not completely useless, and they can help address some otherwise potentially sticky problems. However, as soon as you use Annotations to perform a programming task you are using declarative programming. Java and C# are supposed to be Object Oriented Programming Languages. Build languages like ANT and Make are declarative languages. You declare some tasks and their dependencies and allow the build process to sort it all out. Java wasn’t designed like that, but because there were some aspects of programming that are too hard to do in Java’s version of OOP we introduce annotations.

Annotations provide a way to mix concepts in a declarative fashion.

All the Annotation does is mark something in the class with some sort of tag. In essence it’s like a marker interface for the class, method, attribute, or parameter. The most innocuous use of Annotations is simply to mark a method for documentation purposes. It doesn’t take up compiled class file space or runtime memory, just gets added to the documentation. That’s a reasonable and predictable use for annotations.

The tricky part is when we change what the application does when we use annotations. For example, marking methods as a web service endpoint changes how the method is used. Marking a method as a test method affects how that method is called. Or in the case of Java ActionPack, marking a method with @Filter has more side effects. That method will now never be used for an Action, and the filter will be called before/after all the actions that it applies to. I recently added a convenience method so that you can query whether an action is marked with an annotation or not.

I used this solution so that I could mark all my AJAX support methods with the @AJAXSupport annotation. Why would I want to do that? Two reasons: for documentation purposes, and so that I don’t have the Single Sign On (SSO) service bring me back to an AJAX support page. The system would automatically set a callback URL in a filter applied for every action in the system. If someone called an AJAX support action that returns a partial page result, and then clicks on the SSO link the return URL from the SSO service would be for the partial page result. I had to do something (other than manually listing the actions and testing each one of them) to prevent that from happening. So I added an annotation so that I could check if the action has that annotation or not.

When I explained that to someone on the team, they responded with “I would never have guessed that”. Of course they wanted the equivalent of a modal dialog box on the web—which I believe is bad even in desktop application design. Another complaint was that I was mixing application logic with display logic. To be fair, it is navigation logic which is sometimes considered application logic and sometimes considered display logic in different situations. However, from a pure “separation of concerns” principle I was now mixing concerns in my code.

Does that mean that the solution was bad? It works, and it was the simplest thing to maintain and perform. It does not mean it is the most elegant solution or the purely simple solution. For one thing, I’m mixing declarative logic with object oriented logic. Another problem is that I’m mixing navigation logic with application logic. To some extent you can’t get around that, but that can be a symptom of design smell as well.

So am I saying that Annotations are evil, and because they are mixing concerns and programming paradigms we should avoid them at all costs? No. I’m saying that they trade code complexity for conceptual complexity. The complexity is not really gone from the system, it’s just that it has been moved to a different form of complexity. You might be able to grasp each concept in isolation, but mixing the two will probably make it hard to maintain in the future.

Part of the reason that Ruby on Rails works so well is that they did keep the concepts as simple as they could. There are relatively few rules to learn, and the rules are applied consistently. It was also built on a language that was flexible enough to keep everything object oriented, so there is no need to resort to the declarative annotation model.

Justification for On Complexity

I chose the formula because as soon as you introduce one exception, the human mind has to sort out whether or not that exception applies to this rule. Even if there is one exception to a list of 10 rules, we have to recall whether the rule we are using has the exception or not, and if it does whether the exception is in effect. A list of rules with no exception still has the complexity of deciding which rule (or set of rules) applies so it has a base exponent of 1. You add one exception, and you’ve squared your complexity. For example a set of ten rules with no exceptions has a complexity score of 10, and as soon as you add one exception it becomes 100.

The complexity values have no units and no real meaning other than to provide a relative indication of what you are getting yourself into. It helps you understand the number of decisions the brain has to sort through before it is satisfied that it can predict that you are doing the right thing. Sometimes a little change can provide a huge impact on the relative complexity. The idea is to keep the numbers as small as you can.

When Code Outgrows its Design

Posted by Berin Loritsch Thu, 23 Aug 2007 18:52:00 GMT

I’d like to tell you I get everything right the first time, but then I’d be lying. However, what if I told you I got it wrong on purpose? Would you believe me? That said, the fundamental premise of YAGNI (You Ain’t Gonna Need It) is that you do the simplest thing that can work, and refactor later. The principle behind continuous design is that you put in enough structure to work, and refactor and modify as you go on. As you learn how your application’s structure is growing, you find places where you’ll need to help it out a bit.

One such example is the Controller base class in the Java ActionPack code. I started out with a base structure that I need an instance of a controller, populated with the current request and response objects—similar to how JSPs work. Then I started adding some helper methods to make working with controllers easier. Today, I have a mixture of an object factory (and its supporting structure) and helper methods and attributes. The Controller code is getting pretty big, and it may be hard to draw the line between support and factory related code.

So what do you do? The answer is obvious, you refactor. Now is the time to separate the factory code from the Controller base class. According to the GoF Design Patterns book, the proper way to do a factory is to have a factory class whose whole responsibility is to create instances of a different class. In short one objects makes a whole bunch of another object. So why didn’t I start there? In the beginning the Controller class was primarily a factory itself. We really didn’t need to separate things. YAGNI. Now that the code has grown, and we’ve added a lot more support, the time has come to use the factory pattern as specified in the GoF book.

Designing for Change

It should be obvious, but one of the chief principles of object oriented programming is to hide the details of how to do things, and you just tell objects to do a job. You only make available what you intend users of the object to use. That way we can hide changes to the algorithm without breaking compatibility. For example, now that I’ve identified a weak point in the Java ActionPack code, I need to be free to fix it without breaking every web application using the software. Part of the reason for having the Dispatcher and Controller classes in the same package is to provide package access to the factory methods on the Controller class. That means I can safely make the change because that part of the API was never made available to the average user.

Both public and protected methods are usually exposed to the user in some way. Either they are helper methods such as “redirectToAction”, or they are meant to be accessed from anywhere. Package protected (a Java unique feature) and private methods are typically where the guts of things live. They are hidden APIs that can be adjusted as you wish without fear of affecting users.

Example of Simplicity in Design

Posted by Berin Loritsch Mon, 20 Aug 2007 12:05:00 GMT

It’s all well and good to preach simplicity, but if you don’t provide practical examples then no-one can get it. I’m going to highlight one section of Java ActionPack to show simplicity in action. The first mistake that people make when talking about simplicity is confusing it with simplisticness.

Simplicity is the ultimate sophistication. Leonardo DaVinci

So what does it mean to use simplicity in code? First, simplicity has to do with keeping the responsibilities of your code small and focused . You should resist adding responsibilities to a bit of code unless there is no better place to put it. The org.dhaven.actionpack.Route class in Java ActionPack takes a URL pattern, and set of default values and populates request attributes with the substitution values. That’s it. Nothing else. It’s the controller code that reacts to the special attributes “controller” and “action” to find the controller and action to execute. The org.dhaven.actionpack.Routes class will allow you to register a series of Route objects to evaluate in order. It also provides a method to iterate through the Routes and return when the first match has been found. Pretty sweet, huh? Two classes that have a relationship, but their responsibilities are very small.

Nice overview, but can we look at things in more detail? Sure thing. I wanted to make sure it was easy to programatically set up the Routes you wanted your application to use. If you didn’t want a routes file hanging around, or you wanted to embed this framework someplace I hadn’t expected, it shouldn’t be hard to do. I.e., I shouldn’t have to try and set up an object tree like the Apache Digester based projects. When you try to start from the configuration file format, instead of how you should add new routes to the system it gets really ugly really fast. So I wanted to make it simple , or easy to do. My solution? Why not simply call Routes.connect() ? If you were to set up the routes manually, it would look like this:

public static void setUpMyRoutes() {
    Routes.connect("/{controller}/{action}/{id}");
    Routes.connect("/{controller}/{action}");

    Map<String,String> initParams = new HashMap<String,String>();
    initParams.put("controller", "home");
    initParams.put("action", "index");

    Routes.connect("/{controller}", initParams);
    Routes.connect("", initParams);
}

Notice that I’m only passing strings into the Routes object? In turn, the Routes object doesn’t do anything with these strings other than creating Route objects with the parameters passed in to the constructor. It’s the Route object itself that knows what to do with the provided strings. The initParams map is also a simple map, which provides default values. The default values are overridden by the values interpreted by the URL. What I haven’t done, and I probably ought to do is to make it so that if defaults are present, the same Route can match partial URLs like the Ruby on Rails version of the functionality can. Perhaps that is a future enhancement. Remember, it is only the Route object I have to alter to make that possible. Setting up the Routes is as simple as it gets.

So what if I don’t want to worry about setting up the routing myself? Well, why not create a route parser? That’s exactly what we did. The org.dhaven.actionpack.RouteMapParser handles parsing a very simple route file format that isn’t XML. In fact, it’s similar to the Ruby format (with minor differences). I didn’t want a full on Ruby parser, just a convenient format. If you call org.dhaven.actionpack.RouteMapParser.parseFile() while passing in an InputStream or Reader, you can have it parse the file for you. The parser is very simple as well. First, all routes are completely defined on one line. Second, blank lines and lines that start with the ’#’ character are ignored. Why the ’#’ character? Because it is used as the comment marker in Properties files, shell scripts, and Ruby files. It should be reasonable to assume people know that is a comment. So what does a line look like? Well, let’s do the same thing with our file that we did in the method above.

"/{controller}/{action}/{id}" 
"/{controller}/{action}" 
"/{controller}", action => "index" 
"", controller => "home", action => "index" 

The first part of the line is the URL in quotes. This is the “route” that is being connected through the Routes class. All elements of a route are separated by a comma. That means the route and all default request attributes are separated by commas. The key/value of each map entry is separated by the ’=>’ combination. That separator is a convention used in Ruby and Javascript, but it looks right. No quotes for the key, and the element is surrounded by quotes. There really isn’t much of a reason for this convention other than I thought it looked easy on the eyes. With everything in quotes it got tough to keep straight what were the keys and what were the values. Now, all the key/value pairs are strings. It’s up to you to perform the conversions to other types in the controller if you want. The reason for that has to do with simplicity of design, and not getting the whole route map process too convoluted.

The RouteMapParser takes care of calling the Routes.connect() method which in turn takes care of creating the Route and putting it in our list of routes to match against. Each responsibility is clearly mapped to one class. If someone else wanted a different format for setting this up, there would be nothing to stop them from doing it. It also makes understanding each class much easier. The RouteMapParser only has the responsibility of converting a file to a set of routes. The Routes object only has the responsibility of managing the list of routes and testing a request against that list. The Route object has the responsibility of trying to match the URL, and then populating the attributes if there is a match. The Route object may be expanded in the future to take the parameters and generate a URL from them (as Ruby On Rails currently does), but that is a future enhancement.

The bottom line is that the responsibilities are finite and related to each other. More importantly, the concerns of configuring the system are kept separate from the code that does the work. The number of objects needed to do simple things is very small, and the interactions are well defined and easy to understand. The simplicity allows the objects to be used in ways I may have not foreseen, but that doesn’t really matter. What matters is that the sophisticated uses I haven’t foreseen are because of the simplicity of the classes governing that responsibility.

What's Next for Java ActionPack? 3

Posted by Berin Loritsch Mon, 13 Aug 2007 12:28:00 GMT

Java ActionPack is not complete yet, and there are a few rough edges. One of the temporary work arounds I have is that markup is in my Java code. This is not an ideal solution. These are what Ruby on Rails uses partials for. I need to get the partials code working. Another issue, that I really would like some input on is whether JSP code belongs in the WEB-INF directory. I’m planning on making the View base configurable, but defaulting to where it is right now (the context root). That means all your view code (HTML and JSP) will be in the WEB-INF directory if you so choose. I’ve been told this is an industry practice, but I’ve never seen any examples or articles telling me this is truly the case. Lastly, I need a way of writing URLs based on the action/view/parameters that we set up in the Routes file.

I’ll probably have to do this in two stages. The first being all the hook code necessary to generate these things in ActionPack. The second being a new JSP ActionView library to provide a tag and expression library you can use in your pages. The idea is that if you don’t use JSPs, you can still use the core functionality built in to ActionPack. However, if you do use JSPs, you can simply use the convenience parts to make it nicer.

Of course, the next thing I need is a lot more documentation. I realize that Java ActionPack is at the place where Spring used to be a couple of years ago. It’s still an underground technology that really can make it easier to get things done. It is something that can be used along with Spring if you choose, and at the end of the day it is all about what makes it easier for you to get the job done.

Something that I have been struggling with is how to work with Helpers. In Rails, you have Helper modules that get mixed in to both the Controller and the View logic. It can help clean up code, but in Java there is no real clean way to handle this. I could have a dynamically generated “helper” attribute that gets populated when the controller is instantiated. I could do that through a setter ala Spring, a constructor ala Pico, or something similar. The problem is something that requires much more thought. The controller would probably be an easier proposition than the view.

I’m definitely going to need some help, or this will take a long time. I still want to keep ActionPack very focused and as simple as it possibly can be, but there are some cool things that will make developing applications much nicer coming down the pike.

Java Actionpack: How to protect actions

Posted by Berin Loritsch Wed, 08 Aug 2007 11:51:00 GMT

A very common issue dealing with web applications is how to protect a set of URLs so that only people who have the proper permissions can have access. With Java Actionpack, you would accomplish this through the use of filters. Filters can be called before or after actions, and you can be picky on which actions are supposed to be affected by those filters. Java Actionpack uses annotations to mark which methods on a controller are filters. All other public methods are actions. First, let’s look at the annotation we use:

@Filter(position = {Position}, rules = {Rules}, actions = [])

A closer look at the parameters:

position
Position.BEFORE
The filter is called before the actions.
Position.AFTER
The filter is called after the actions.
rules
Rules.ALL
The filter is called for all actions in the controller, no matter what the actions list parameter says.
Rules.INCLUDE
The filter is called for only the actions listed in the actions list parameter.
Rules.EXCLUDE
The filter is called for all actions not listed in the actions list parameter.
actions
The list of action names (method names in the controller) that this filter may affect depending on the rules. The default value is an empty list, so it can be omitted when you use Rules.ALL

The first thing we need to worry about is how many of the actions need to be protected. Is the controller for an administration section where we would need to protect everything? Is the controller for general browsing, but we only need to protect just a couple of methods? Or possibly the controller is for the user self-management so we would need to protect everything except for the login and self registration actions. The only difference is in how we set up the filter. Just to keep things simple, let’s assume the controller is for an administration page.

public class AdminController extends Controller {
    public static final String ADMIN_ROLE = "ADMINISTRATOR" 

    @Filter(position = Position.BEFORE, rules = Rules.ALL)
    public void ensureUserIsAdmin() {
        if ( ! request.isUserInRole(ADMIN_ROLE) ) {
            sendMessage(
                "You don't have permissions to access the administration pages.");

            if ( null == request.getRemoteUser() ) {
                request.setAttribute(ActionPack.CONTINUE, getThisUrl());
                redirectToAction("security", "login");
            } else {
                redirectToAction("home", "index");
            }
        }
    }
}

There’s a lot going on here. First, we have to check if the user is in the administration role. Once we know that, we can decide what to do. First, we send a message (this message is identified by a request attribute that Actionpack will forward through redirects). Next we determine whether the user is logged in or not. If the user is logged in we redirect them to the the action for HomeController.index. If the user is not logged in, we redirect them to the login page, with another special forwarding attribute so that the login section knows to come back to the original request. Don’t worry, the credentials will be checked again after a successful login.

So what’s the deal with request.isUserInRole() ? It’s a standard method on the HttpServletRequest object, and even if you don’t use container authentication, you can still use it in your application. Java Actionpack provides an interface that you use so that it knows what to do with your User object. The interface extends the java.security.Principle interface so that your User object is compatible with the request.getRemoteUser() and request.getUserPrinciple() methods. The user interface also extends java.io.Serializable so that it is compatible with session attributes in servlet engines that are compatible with the newest standards. Lastly, it provides one more method: isInRole(String) . The method is used so that the request wrapper can determine if the user object is in a the requested role.

So where do you put this object we created? The RequestWrapper looks in a session attribute identified by ActionPack.USER, which is the fully qualified class name for the User interface. So your login code will need to create an object that implements actionpack’s User interface, and place it in the session attribute ActionPack.USER and everything works as expected.

Filters are Inherited

When you set up a filter on a controller, you can extend the controller and any filters in the base class also apply to the derived class. For example, if you set up some filters in an abstract ApplicationController used as a base class for all the controllers in your application, those filters are now applied to all the controllers in the system—obeying the rules set up in the filter declaration of course. One possible use for this include sending a “Testing” disclaimer message that only applies when the application is set up on a test server. That message would show up on every page, along with any error messages that use the sendMessage system. I’ve also used it to manage a toolbox that is populated depending on what roles a user has, and possibly which controller the user is accessing (i.e. some tools are only accessible some of the time while others are there all the time). Use your imagination with applying them.

How to get started with Java ActionPack

Posted by Berin Loritsch Mon, 06 Aug 2007 12:45:00 GMT

I’ve left hints about my Java Actionpack, but there really isn’t much out there about it for the general world. So how about I give you a quick primer about how to use it? First off, you will have to check it out with Subversion. There’s a slight conflict with the web site being pulled from SVN and browsing the repository, so you’ll have to use the SVN client instead of mounting the directory or browsing it online. I’ll have to work with my ISP on that.

svn co http://d-haven.org/svn/open/trunk/actionpack

It’s world readable, but only authorized people can write. For now, that’s just me but I’ve not really solicited any help at this point. Since that’s not the point right now, let’s worry about how to get it installed and running. Once you’ve checked it out, you’ll need to build it. Go to the directory where you checked it out and build it with ANT . Yes we kept it simple and only used ANT.

ant jar

The ant script builds two jars, “java-actionpack.jar” and “java-actionapack-test.jar”. The first file is what you will include in your webapp to make the magic happen. The second jar provides the helpers and mocks to help you test the controllers in your application. I’m assuming at this point you know how to set up a web application, how to include your code, and configure a web.xml file. So I’m only going to talk about what is specific to Java Actionpack. Obviously, java-actionpack.jar goes in your WEB-INF/lib folder. You’ll need to add the following to your web.xml file to use Java Actionpack:

  <filter>
     <filter-name>ActionPack</filter-name>
     <filter-class>org.dhaven.actionpack.Dispatcher</filter-class>
     <init-param>
       <param-name>routes.file</param-name>
       <param-value>WEB-INF/app.routes</param-value>
     </init-param>
     <init-param>
       <param-name>controller.package</param-name>
       <param-value>com.mycom.app.controllers</param-value>
     </init-param>
     <init-param>
       <param-name>environment</param-name>
       <param-value>development</param-value> 
<!--       <param-value>test</param-value> -->
<!--       <param-value>production</param-value> -->
     </init-param>
  </filter>

  <filter-mapping>
    <filter-name>ActionPack</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

The only thing that is critical for you to add in is the “controller.package” parameter. This tells Actionpack where to look for your controllers. By default it is simply “controllers”, but that doesn’t really make sense for most people. The default value for “environment” is development, and this really is a way to help you to have logic depending on what environment you are in. The framework will log a message each time a controller is called with an action that doesn’t exist. The message won’t be logged in testing or production. I’ve used it to provide a message about the testing data that our client requires but shouldn’t be there in production. You can access it in your code by looking at the static variable Controller.environment, and the value is from the Environment enum. Finally the “routes.file” parameter allows you to override the default location for the routes file. The default value is what you see in the configuration snippet above.

So what happens if you don’t have a routes file at all? Java Actionpack will create some wiring for you. It will provide the following mappings by default:

/{controller}/{action}/{id}
/{controller}/{action}

That will provide the familiar mapping of what controller you want, which action on that controller, and the option of passing an ID. The way the routes file works is that the curly brackets refer to a request attribute . So why attributes instead of parameters? Mainly so that the application isn’t so easily manipulated by anyone who knows how to type URL parameters. The request attribute controller specifies which controller you are calling. The controller is inside the controller package you set up, and it transforms the name so that it capitalizes the first letter and tacks on Controller to the end. For example if the request is /message/view/34 and you use the configuration above, the class that Actionpack finds is com.mycom.app.controllers.MessageController . The action attribute specifies the method that will be called. With the example URL, we will call MessageController.view() . It’s up to the view() method to read the id attribute and do something with it. Let’s implement this example method:

public class MessageController extends Controller {
    public void view() {
        String id = (String)request.getAttribute("id");

        request.setAttribute("message", Messages.findById(id));
    }
}

You might wonder why I chose to place the message object into the request attribute. It’s really up to you where you put it (the RequestWrapper allows you to override request parameters as well), but this works well if you use the Expression Language and JSPs. You would just refer to the object in the parameter marker like this: ${ message.body } . This calls the method getBody() on the message object you passed in to the request attribute. You’ll also notice that the request object is available as a class attribute, as well as the context object and the response object. They follow the same format as you would expect for a JSP class to keep things familiar. I.e. the names are “request”, “context”, and “response” respectively.

So what about the view? Since Java Actionpack is supposed to be as non-intrusive as possible (yet still opinionated), Java Actionpack will look in the WebApp context for the file called by the controller/action name. So for our example URL from above, we would look at “message/view.jsp”. The progression is this: it looks for a JSP file (”.jsp”), then an HTML file (”.html”), and then finally is just passes the url “message/view” to the system to process. If you want your own supercool view technology as a Servlet, then you just have to set it up to react to the URL scheme we just outlined. Java Actionpack is a filter, but it uses the request dispatcher to pass that URL on. We favored the JSP technology partly because more people would be familiar with it, and partly because it finally grew up enough to be nice to use.

So what happens if Actionpack can’t do anything with the URL? Let’s say the request comes in for “index.html” or “site.css”, or even “fantastic/example.pdf”. If the “controller” attribute doesn’t match an existing controller, Java Actionpack gets out of the way, and lets your application deal with it as it normally would. If the controller is matched, but there is no method for the action attribute, Actionpack will process any filters set up in the controller and process the action calling the action_missing(String actionName) callback (which by default will log what happened in DEVELOPMENT mode). Finally it will dispatch to the view as it normally would. It comes in useful when you have to protect a whole bunch of actions that need a user to have a certain role, but some of the pages are static. Why should you have to create a method if there is nothing to do in it?

These are the basics, and there’s more to it. But for now, I just wanted to share how to get it downloaded so you can play around with it. It should feel natural to a Java developer, and natural enough to someone who has experience with Ruby on Rails. I’ll have to do a few more focused tutorials with it.

Better is Better, not More

Posted by Berin Loritsch Tue, 31 Jul 2007 16:00:00 GMT

In this day and age, we are used to having more and more shoved in our faces. We go to a coffee shop and we have to figure out how caffeinated, flavored, and masked over we want our coffee. Because of all the crap that they put in your $5 cup of coffee you can’t tell if the beans are burnt, replaced with dirt, or if the coffee is actually good. The overwhelming choice is there to make the coffee user feel empowered over their addiction. I happen to like my coffee, but the exorbitant prices and crappy coffee keep me from going to places like $tarbucks.

The same thing has made its way into the world of photography. People behind the counter at your local camera shop have the audacity to say that digital makes you a better photographer because it’s easier to take a butt-load of shots ! I don’t know about you, but something like that smells bad in my mind. A butt-load of shots with no thought put into them are just as bad as only 36 shots with no thought put into them. Yet they tell you these things because they need to move these $1000 cameras off their shelves, and people buy them thinking this magic bullet will suddenly make them better. The cameras come equipped with all this auto-focus, auto-exposure, auto-forget-about-thinking stuff and people think that if the camera takes care of everything they will be good. If you want a camera that does everything for you, save some money and buy a point and shoot camera. They do everything the big boys do and cost hundreds less.

But the point is not about the rant on cameras. It’s the rant on a false sense of security , and the “silver bullet” mentality we tend to get ourselves into. When it comes to the designer’s view of the world, there is a very difficult balance between enabling your users to be better and turning your users into brainless idiots. Take for instance the View camera. That’s the camera pictured in this post. It’s a large format camera, which means that it is slow to set up a shot, expensive to take a picture, and requires a lot more thinking in advance. So why have one? Photographers who learn how to use these properly become better with all their cameras because they are forced to think more about what they are doing before they do it. It’s the thought that makes the users better, not the camera or the fact that it is slow and expensive to operate. Those are side-effects of providing all kinds of operations that normal cameras just can’t do. You can have a several thousand dollar Hassleblad with a tilt-shift lens, and you won’t be able to match what you can do with a view camera. They are different beasts altogether. Granted, you probably won’t be able to tell the difference when the pictures are small. But when you blow your picture up to over four feet tall you’ll be able to tell.

Too much automation is just as damaging as not having enough automation. The balance we need to strive for is to help the user think about their job and not the tool . Its about finding the right options and the right level of automation for the task at hand. Sometimes the point and shoot is the right tool for the job. Sometimes you really need to take your time and craft things perfectly. Sometimes, removing all automation is the right thing to do.

If we start with the premise that everything can be done manually, we start creating the libraries with that in mind. That’s how picocontainer was conceived. If we want to add automated plumbing, we do that on top of the core. Scripted wiring of your components? That’s built on top of the fully manual core. Even though I don’t use that project, its mere existence forced me to rethink some things about automatic plumbing some time ago. The same thought processes went into the Java ActionPack library (Yes, I know I need to put more of a web presence up for that project).

So what about automating the parts that are annoying to do each and every time? Absolutely. We shouldn’t be forced to think about things we don’t want to think about. The more we get the machine to do things like creating a build, branch, etc. the more we can get them to be done consistently. However, some things can’t be done automatically, nor should they. When you evolve your code’s design you should be thinking about what you are doing. However, if you want to do simple things like rename a method, it helps to have your editor find every instance where the method is used and change your code for you. That’s not something you want to spend time thinking about.

How do you Measure Quality? 4

Posted by Berin Loritsch Tue, 24 Jul 2007 12:43:00 GMT

I’ve always been of the opinion that quality cannot be measured. Truly, quality is subjective to the viewer, and it is hard to convey what quality is let alone measure it. Sure, the CMMI zealots and process weenies tell you that you can measure things like “defects over time” or “size of code per function” but does that really give an indication of quality? They only hint at relative aspects of a certain slice of quality.

If I told you that the size of our application dropped from 50MB to 1.2MB and it had more functionality would it grab your attention? It might for a little bit, until I mentioned we had to rip out and throw away the old framework and rewrite the app from scratch to do it. I might keep some of my audience’s attention if I said that the complete rewrite happened in a period of 12 man weeks. (That’s manager speak for it would take one man 12 weeks of work, which leads to the fallacy that it would take two people 6 calendar weeks).

What if I told you that we had a quarter of the reported defects per week than the old version of the application? What if I said the time to close the defects went down by more than 100%? I bet most of you would have this lingering doubt thinking that we are fudging our numbers. Does this mean that the application is truly better inside and out? It certainly means it costs less to produce—but that doesn’t mean its a better quality.

BTW, all these things are true events of when we ripped out the Cocoon core of our application and replaced it with my new Java ActionPack framework. So does this mean that Java ActionPack is better or higher quality than Cocoon? Again, that’s a matter of opinion. I think it’s safe to say that Java ActionPack is a better fit for our application, and it is likely to be a better fit for other applications as well. I hesitate to say it is better or higher quality because it really depends on your point of view.

So, what is quality? How can we improve quality in our applications? And for the pointy haired types, does improving quality improve our bottom line? There are a whole bunch of philosophical bain brending exercises you could go through to come up with an academic view on quality, but then you’d only have scratched the surface, and you’d probably be ready to go down the road of insanity. The thing is that we know what is good quality in our guts. It has a certain feel. It’s hefty, it just works, it feels right.

I think the artistic world has a better handle on quality, mainly because they aren’t hung up on having to explain every jot and tittle to show off how smart they think they are. Yes, academia, this is a dig on you. Things like elegance, naturalness, fit, finish, and an overall sense of right cannot be explained. They can be coached, the can be passed on from master to apprentice. However, they can’t be truly explained—nor can they truly be measured.

The closest measure of quality that we have with Java ActionPack over Cocoon is this:

Everything is where you would expect it to be. I can understand it. It’s so easy a caveman can do it.

The smart pointy haired types (isn’t that an oxymoron?) will notice that I dodged the question on “will a pursuit of quality affect the bottom line?” The short answer is that yes it will. The long answer tells you why, but suffice it to say that Java ActionPack was driven out of a desire to pursue quality, simplicity, and elegance. The drop in application size, the increased efficiency (both in application performance and the developer’s work), etc. are all consequences of that. It wasn’t just throwing out Cocoon and using Java ActionPack. It was the fact that with the fresh start, we focused on quality in every aspect of the new version.

The problem is that pointy hair types want a magic wand to waive and an incantation to say to make everything better. So as they are constantly banging on the Staples button like a chimpanzee saying “that was easy,” the rest of us have to discipline ourselves. TDD by itself isn’t going to give you a good design. After you make your tests pass, you have to ask yourself if the change makes things better. What does the change enable you to do that you couldn’t do better before? It’s through this iterative process that your design evolves and the statue hiding in that block of marble starts to emerge. It’s not like it takes a lot of time, but it takes the willingness to undo something you did when you find out that the small change doesn’t fit the application from the big picture. Local changes are always subject to the larger picture. You’re looking for better and beautiful. You aren’t looking to impart a preconceived idea of design on the app, but to let the app design itself as it were.

Older posts: 1 2