by Bear Bibeault One sometimes unexpected side-effect of moving to JSP 2.0 "scriptless pages" is the amount of thought it forces one to focus on the "controller-to-view interface". To me, this side-effect is another major advantage (in addition to the welcome simplification of the pages themselves) to making this transition. "How on Earth is forcing me to actually think of something an advantage?" you may ask. My answer to that is that more thought to this interface usually means a better interface. And better interfaces equal better program structure. And unless you haven't written a line of code in your life, you know that better program structure equals happier programmers. Now it's not that there's never been any thought given to this interface before, it's just that in the pre-scriptless era it was common -- because it was just so easy -- for us to code the controller servlet to throw any old data structure onto the request knowing that we could write all the Java we wanted on the page to deal with those structures. Some of us, and I'll give myself credit to be among those, always had the notion that the less Java on the pages, the better, and gave some amount of thought to gearing the structures passed as request-scoped variables to the needs of the page. But still, because any arbitrary Java code could be included on-page, it wasn't a paramount consideration. That has all changed. With scriptless JSP pages, where JSP 2.0 Expression Language (EL) expressions are the primary means to reference the scoped variables, adjusting the nature of the scoped variables to suit the pages becomes something to which more thought must be applied. Over the course of converting a number of my client's web applications to use JSP 2.0 and scriptless pages, I've learned a lot about structuring the controller-to-view data, and one thing that has become apparent to me is the overlooked power of the Map as applied to this problem space. By "Map", of course I mean implementations of the Recall that in the Expression Language, the fetch operators (the dot and the square brackets) tailor their semantics to the type of their left operand. In the EL expression:
${xyz.abc} or the equivalent ${xyz['abc']} how the EL evaluator determines the value of If If however, This is powerful stuff and opens up the usage of the Map in this context in ways for which we might not previously have thought of using a Map construct. A Case Study: Member PermissionsOne of the web applications that I have updated to use scriptless pages is a community-based recipe sharing site. The app is membership-driven, with each member assigned to a "role" that grants them certain permissions for the various actions that can be performed within the application. Lowest is the guest role where unregistered visitors can browse the site contents. Registered visitors with the member role can submit recipes to be added to the site contents. Paid members with the gold member role can create private recipe collections and have access to some other advanced features. Moderators can approve submitted recipes, remove member accounts, and perform other policing actions. The most privileged role of administrator can perform all site actions. Each role is actually a set of discrete permissions that determine what actions visitors possessing that role can initiate. The "add recipe" permission, for example, is granted to all roles but "guest". Each visitor to the site is identified via an instance of a If we imagine a location on the site where an "Add Recipe" button will appear for those visitors that have the "add recipe" permission (which would be all but "guests"), you might have seen JSP code like this: <% Member member = (Member)session.getAttribute( "member" ); if (member.hasPermission( "ADD_RECIPE" )) { %> <button type="button" onclick="onAddRecipe()">Add Recipe</button> <% } %>
Converting this to a scriptless equivalent using JSTL tags and the EL might seem straight-forward at first, but when we try to access the "hasPermission" method of the member object, we run into problems. The EL can easily access properties of objects such as The means to determine whether a member possesses a particular permission needed to be changed to a mechanism that was "EL-friendly". One tactic could have been to replace the general purpose method with discrete property accessors. Under this approach each and every permission would need to become a property of public boolean getHasPermissionAddRecipe(); public boolean getHasPermissionApproveRecipes(); public boolean getHasPermissionBanMember(); ... and so on.
I rejected this approach due to a number of problems. Not only did it not scale well -- as the number of permissions grows, so do the number of accessors necessary -- it artificially makes each individual permission a property of The next thought that occurred to me was to consider using EL functions. Since the problem seemed to be that EL property expressions didn't allow for general function calls, perhaps defining some EL functions would do the trick. EL functions are means to access static methods defined on a Java class. By creating a static function, perhaps on the In a TLD file, such a function could be defined as: <function> <name>hasPermission</name> <function-class>com.whatever.membership.Member</function-class> <function-signature> boolean hasPermission( com.whatever.membership.Member, java.lang.String permission ) </function-signature> </function> and on-page, its usage would be (assuming that the TLD containing the function was declared and mapped to the prefix 'membership'): <c:if test="${membership:hasPermission( sessionScope.member, 'ADD_RECIPE' )}">... Although I liked this solution much better than adding individual properties for the various permissions, I thought that it was a bit wordy on the page, didn't read well at all, and the static nature of the method seemed like a bit of a OO wart on the What I really needed was a different means to map the name of a permission to its granted/denied setting. Light dawned when I finally realized that the solution was in the problem statement itself all along: I needed a means to map the name of a permission to its granted/denied setting. Thinking back to our previous example of My solution was to create a new property for the Hence, its accessor is: public Map getHasPermission(); and it can be used on-page thusly: <c:if test="${sessionScope.member.hasPermission.ADD_RECIPE}"> <button type="button" onclick="onAddRecipe()">Add Recipe</button> </c:if> which makes for a beautifully readable EL test expression for the All it takes is to add the permission names to be tested as a key to the Map -- in our example "ADD_RECIPE" -- with a value that evaluates to true (such as Since the expression will evaluate (and without error) to false in the event that the Map lacks a specific key, we need only add granted permissions to the Map. Any denied permissions need not be explicitly added with a value of While this does indeed make access from the JSP page very readable, the signature of the accessor is rather odd-looking when used from Java code (permission checking is also performed quite often within the server-side code). But this need not be an issue since nothing prevents us from leaving the original
Another Case Study: ConstantsA recent post in the JSP Forum of the JavaRanch Big Moose Saloon brought up another interesting case study. In the post, the author -- another firm believer in the "goodness and light" of scriptless JSP pages -- lamented the fact that without scriptlets or scriptlet expressions, it was impossible to reference static constants defined in Java classes. Indeed, using the facilities of the Expression Language, this is not possible. Such references proved quite useful in pre-scriptless applications. Take for example, a common bug introduced by a simple typo naming a form element on a JSP page. Let's say that in servlet String description = request.getParameter( "description" ); But on the page, the form element is coded as: <input type="text" name="decsription"/> This error causes the request parameter value in the servlet to always be null since no form element with the expected name actually exists. This type of bug is easy enough to fix, but can waste a great deal of time trying to find. By using a string constant defined on the servlet (or in some other abstraction as we will discuss later): public static final String KEY_DESCRIPTION = "description"; this type of bug can be avoided by using the constant in the servlet itself: String description = request.getParameter( KEY_DESCRIPTION ); and within the JSP as: <input type="text" name="<%= SomeServlet.KEY_DESCRIPTION %>"/> assuming that While this may be somewhat notationally heavy, it has the distinct advantage of generating a compile-time error should any typo in the key reference be made. Within a JSP 2.0 scriptless page, such scriptlet expressions are not possible. And while even the power of the Map cannot achieve the invaluable utility of a compile-time check, it can be used to make such errors at least a little easier to spot. Let's take the well-known example of a simple login form which consists of two entry fields: a username and a password. Knowing that simple string constants exported from a servlet, or any other class for that matter, will have no utility for our scriptless JSP pages, we'd like to use a Map to create references that can be readily and readably used on the JSP pages. Since we're going to be exporting more information about the form and its elements than a simple set of string constants, it makes sense to formalize an abstraction of our "form" and its elements, decoupling it from any one specific servlet (or page). In this abstraction we'd like to export information that is usable from any servlet that deals with our "login form", as well as from the JSP page that will implement the UI elements that present the login form to the user. Here's how it might be done: public class LoginForm { public static final String KEY_USERNAME = "username"; public static final String KEY_PASSWORD = "password"; public static final Map FORM_KEYS = new HashMap(); static { FORM_KEYS.put( "KEY_PASSWORD", KEY_PASSWORD ); FORM_KEYS.put( "KEY_USERNAME", KEY_USERNAME ); } } In this class the form keys are exported as string constants that are easily used by any Java code (particularly servlets) that need to reference them. A Map of the form element keys whose keys are named using the conventional naming format for constants is also exported. When placed onto request scope by code such as: request.setAttribute( "FormKeys", LoginForm.FORM_KEYS ); the form elements in the scriptless pages can now be coded as: <input type="text" name="${FormKeys.KEY_USERNAME}"/> <input type="password" name="${FormKeys.KEY_PASSWORD}"/> Because of the names and naming conventions we used to create the Map and the scoped variable, the purpose of the references is immediately recognizable as mimicking constant values.
Operationally, if the While this is nowhere near as useful as having a compile-time (or even run-time) error thrown that reaches out and slaps you in the face, a typo in the JSP page now results in a pattern that should be easier to spot by inspection, as well for which automated searches can be created. If, for example, the following error is made: <input type="text" name="${FormKeys.KEY_USRENAME}"/> the resulting rendered HTML would be: <input type="text" name=""/> which would be easier to spot in the rendered page than a hard-coded typo like: <input type="text" name="usrename"/> and for which it is easy to create an automated search that finds instances of the Whether it is worth all this setup for what some might think is marginal gain is up to the individual to decide. I include it here as another example of how a Map can be used in conjunction with JSP scriptless pages in ways that might not be obvious.
SummaryIn this article, we've looked at a number of ways to use the Map interface in conjunctions with JSP scriptless pages. Because Map keys can be referenced in an Expression Language expression as if they were properties, the Map provides a clever way to create "property names" that are not, or cannot, be known at compile time in a way that is not possible with formal JavaBean properties. Return to Top |
||||||||||||||||||||||||||||||||||||
More About Conversions by Corey McGlone This month we're going to do a quick extension of my last article. In that article, we looked at the various types of conversion and casts that can be done in Java. This week, I'm going to look at a specific trick with casting that may very well appear on the exam - it most certainly appears on most mock exams. Assignment Conversion vs. Method Invocation ConversionLet's start off by taking a look at this code snippet:
So what's the output of that code? I sure hope you said that it produces a compiler error, because it certainly does. Let's take a look at all of the conversions that are taking place in that code - believe me, there are a lot. Let's start at Line 3, which is the first line that will be executed. What data type is 50? Any integral literal is always considered an int by the compiler. Therefore, line 3 is passing an int to a method that takes a byte as a parameter. This is where our compiler error comes from. Passing a parameter to a method invokes a Method Invocation Conversion. A method invocation conversion can only perform an identity conversion (such as casting a byte to a byte, which is trivial) or a widening conversion. Obviously, casting an int to a byte is a narrowing conversion, so the method invocation conversion can't handle it. Hence, the compiler error. If we were passing a byte to a method that took an int, no problem - that's a widening conversion. But an int to a byte? That's a no-no. Let's modify line 3 to read like this: byte b = myMethod((byte)50); What does that do for us? Well, by first casting the int to a byte (through our explicit cast), we are passing a byte to a method that requires a byte. That's just an identity conversion so the method invocation conversion works just fine. So now let's jump to Line 2. There's a conversion happening here, as well. What type is 32? Obviously, 32 is an int, just as we saw that 50 was an int. What conversion is happening here? Well, look at the return type of that method - we're supposed to return a byte. But we're returning an int! That should cause a compiler error, right? Wrong. Rather than using a method invocation conversion to perform the conversion, the compiler is going to use an Assignment Conversion (essentially assigning the value being returned to the return variable). There's a trick to an assignment conversion, though - the following comes straight from the JLS: "Assignment conversion occurs when the value of an expression is assigned (?15.26) to a variable: the type of the expression must be converted to the type of the variable. Assignment contexts allow the use of an identity conversion (?5.1.1), a widening primitive conversion (?5.1.2), or a widening reference conversion (?5.1.4). In addition, a narrowing primitive conversion may be used if all of the following conditions are satisfied:
Essentially, that says that you can automatically assign a value to a variable, even if that assignment would require a narrowing conversion, as long as the value is known at compile time (a literal value, as we have here, or a final variable) and that value "fits" into the target type. In our case, we're trying to assign 32 to a byte. Well, 32 is a literal, so we know the type at compile time and it certainly falls within the range of a byte, which is from -128 to 127. Therefore, the Assignment Conversion handles this conversion automatically by doing an automatic narrowing cast. ConclusionShort update this week, but an important one. The differences between method invocation conversions and assignment conversions are small, but important. Certainly, such details about conversions can be considered "nit-picking" but a lot of the SCJP exam falls into that realm. The idea behind the SCJP exam is to have a good handle on the details of the language and I've seen questions about this material on many mock exams and the real SCJP exam.Until next time, Corey Return to Top |
||||||||||||||||||||||||||||||||||||
by Ernest Friedman-Hill Recently I read Christopher Diggins' article "Programming with Contracts in C++" in the March 2005 Dr. Dobb's Journal, and it got me thinking about Programming with Contracts (PwC), a concept first explicitly articulated by Bertrand Meyer in the Eiffel programming language. In PwC, you not only code the logic for a method, but assertions about the method's preconditions (what must be true for the method to be called) and postconditions (what must be true after the method is called.) What's the difference between PwC and the perhaps more common term Design by Contract? In practice, not much. In theory, DbC is a pure design activity, but of course, contracts are useless unless they are executed. Once they are executed, you're programming, and hence doing PwC. Six of one, a half-dozen of the other. In PwC, the assertions can execute every time a method is executed, although typically they're turned on only during testing. This executable contract provides fine-grained assurances about an application that unit testing alone can't. Postconditions can test the effect of calling a method, which is quite like what you get from unit testing, but preconditions test how a method is called by an application, and thus they give you the benefits of very fine-grained and thorough application testing. In Eiffel, pre- and postconditions are added directly to the code. It's a powerful technique. The downside is that code with a lot of conditions is very cluttered. It's very similar to adding assertions to C or Java source: a few assertions provide useful information about the code, but thorough contract descriptions make it hard to see the implementation for the trees. There are PwC tools for Java; perhaps the first was the now-defunct iContract. With iContract, you defined your pre- and postconditions using special Javadoc tags, directly in a class source. A current Java PwC framework, jContractor, lets you define your contracts in separate classes, and doesn't use a special expression language, but instead uses a number of special naming conventions to connect pre- and postconditions to the methods they apply to. Furthermore, jContractor uses bytecode instrumentation, which affects your build process. I was hoping for something simpler. Diggins' approach to PwC in C++ interested me because it's interface based. For Diggins, a contract is a class that can act as a wrapper for the class it describes. Each method in the contract class simply implements one method in the interface of interest by asserting preconditions, forwarding the call to the implementation object, then asserting postconditions. The nice feature of this is that the contract can be arbitrarily complex without complicating the described class's implementation. Furthermore, this lets you write a single contract for an interface, and apply it to all implementations of that interface. Best of all, it requires no special tools, special syntax, or special rules -- and you can start using it right now. A Tutorial ExampleLet's say you have an Account interface that represents a financial account: public interface Account { String getCustomerName(); void debit(double amount); // More ... } Furthermore, let's say you imagine that while there will be many implementations of this interface, they're all going to have to follow certain rules. For example, getCustomerName() should always return a non-null, non-zero-length String, and debit() should be called with a positive argument less than or equal to the current balance. You can write a contact for Account that looks, in part, like this: public class AccountContract implements Account { private Account m_impl; public AccountContract(Account impl) { m_impl = impl; } public String getCustomerName() { String result = m_impl.getCustomerName(); assert result != null : "Customer name is null"; assert result.length() > 0 : "Customer name is empty"; return result; } public void debit(double amount) { double balance = getBalance(); assert amount > 0 : "Debit amount nonpositive"; assert amount <= balance : "Debit amount would overdraw"; m_impl.debit(amount); assert getBalance() == balance - amount : "Computed balance incorrect"; } // More ... } I've used standard Java assertions to implement the pre- and postcondition checks. An alternative would be to use unchecked exceptions. The advantage of using assertions is that they can be turned off easily via a runtime configuration switch. Another alternative would be to use checked exceptions -- i.e., to require that the interface methods declare an exception that they can throw when conditions are not met, and then throw them from the contract class. Although this latter solution is rather heavyweight, it could be appropriate in certain situations, such as in testing EJBs or JDBC drivers or any other category of classes in which all methods are already defined to throw a specific exception type. The centerpiece of each method of the contract is a call to the corresponding method of the m_impl object. Note how I'm always careful to call the implementation method once and only once; you must make sure that the meaning of the code won't change if assertions are turned off. Now you can test any implementation of Account by "wrapping" an instance inside an AccountContract, and using the AccountContract as if it were an instance of the class under test. Because all our assertions are in AccountContract, the AccountImpl class is very simple: public class AccountImpl implements Account { private String m_name; private String m_acctNumber; private double m_balance; public AccountImpl(String name, String acctNumber) { m_name = name; m_acctNumber = acctNumber; } public String getCustomerName() { return m_name; } public void debit(double amount) { m_balance -= amount; } // More ... } PracticalitiesYou can use a factory to hide this process of creating the contract object: public class AccountFactory { public static Account get(String name, String acctNumber) { Account acct = new AccountImpl(name, acctNumber); if (Account.class.desiredAssertionStatus()) return new AccountContract(acct); else return acct; } } The java.lang.Class.desiredAssertionStatus() method (introduced in JDK 1.4 as part of the assertions facility) basically just returns true if assertions are enabled. It's a convenient way to select the appropriate behavior for our factory. In this case, the implementation class has no default constructor. In practice, you may want to insist that all your implementation class do have one and have a standard initialization method the factory can call. This would make it easier to configure the factory at runtime, or to construct different implementation classes using an Abstract Factory pattern. ObservationsThis form of PwC is useful whenever an interface is going to be implemented multiple times, especially if those implementations are going to be done by multiple people or teams, or if they will evolve over time. It's slightly less useful if an interface will be implemented only once, as then the implementor most likely understands the contract well already. Still, PwC could be used even then to check that the class was being used correctly by implementing preconditions. PwC obviously has a significant impact. For the very simple class being tested here, it's obvious that there is more code in the pre- and postcondition checks than there is in the AccountImpl class itself. PwC, like the assertions I've used here, is generally used only during development and testing, and turned off during production. Java's assertion facility makes it easy to turn assertions on or off at runtime for an entire application or even for individual packages or classes, making assertions an especially convenient way to implement PwC. Contracts check both problems with the behavior of a class and problems with how a class is used. For this reason, they provide some of the benefits of both unit and application tests. Using contracts doesn't excuse you from writing unit tests, but it does provide excellent integrity checks during application testing that otherwise wouldn't be done. All the code for this article is available here. Return to Top |
||||||||||||||||||||||||||||||||||||
by Carol Murphy Whut in tarnation?
The Cattle Drive forum is where the drivers get together to complain, uh rather, discuss their assignments and encourage each other. Thanks to the enthusiastic initiative of Johannes de Jong, you can keep track of your progress on the drive with the Assignment Log. If you're tough enough to get through the nitpicking, you'll start collecting moose heads at the Cattle Drive Hall of Fame. Straight shootin'...
Fresh riders on the Drive... Another moose on the wall for... Get along, little dogies... Juliane Gross has reappeared from where ever she has been holed up. Sure am glad to see folks back on the trail! Behind the scenes... Me, I'm wondering how the heck it has got to be August already. Seems like summer just began! Well, here's hoping to see more of you out on the trail, or just finding the time to hang out more at the ranch. Mosey on over to The Cattle Drive Forum in The Big Moose Saloon! Return to Top |
||||||||||||||||||||||||||||||||||||
Ship It! by Ernest Friedman-Hill Author/s : Jared Richardson, William A. Gwaltney Ship It! is both a guide to running successful software projects, and a life preserver for projects that are failing. If you've ever worked on a troubled software project, you know what it feels like. The frustration. The sense of impending doom. The urge to polish your resume. We've all been there. So have Richardson and Gwaltney -- and they're offering to leverage their considerable experience to help save you and your project from this fate. There's not much material that's truly new between these covers, but the presentation and point of view is refreshing. It's a rare book that speaks convincingly to both developers and managers, but this one does a good job. The book describes many of the practices of agile development -- continuous integration, automated testing, lightweight planning -- and combines them into a simple but powerful description of an approach to building software they call "Tracer Bullet Development." But the book doesn't assume you're going to do everything the authors suggest: they expect you to try just one thing as a time. My favorite part of the book is compendium of one-page essays on common problems software projects have, and how to apply the principles and practices from the book to solve them. Unlike some other rather strained "antipatterns" catalogs that I've read, this section feels very practical and usable. If your shop has trouble shipping quality software on time -- and let's face it, most do -- then this book is for you. If you're a manager, I'd say that doubly so. More info at Amazon.com More info at Amazon.co.uk Discuss this book review in The Big Moose Saloon! Return to Top |
||||||||||||||||||||||||||||||||||||
by Thomas Paul We're got a whole mess of book giveaways coming up in the next few months. Find out how to win a free book! Here are the promotions scheduled for the rest of August.
Return to Top |