There's a couple of other sessions I should probably go to, namely Juergen's talk on Transactions and Mark Fisher's Message Driven POJOs Rock! However, transactions is generally a pretty boring topic and I don't see myself developing any MDPs in the next two weeks. If you don't use your knowledge in two weeks, you generally lose it, so I'll wait to learn more about MDPs until someone pays me to. I know a fair bit already, so I don't know that there's a whole lot more to learn.
I'm attending Rob Harrop's Rapid Web Application Development Essentials talk. With any luck, I'll learn some new tips that we can use in AppFuse.
- Recipe for rapid development
- Basic Tool Set
- Accelerating Spring MVC development
- Exploiting Web Flow
- Cool tools to save you time
The recipe for rapid development is an easy compile/test cycle (eliminate deployment), an easy deployment for view testing (hot deploy, auto-detect changes) and reduce repetition (can often be fixed with convention over configuration, especially by defaulting model and view names). In addition:
- Encapsulate common patterns: binding and validation, multi-page navigation, redirect after POST
- Reusable tools for common tasks: site-wide formatting, layout, testing and monitoring
- Plan and design for maintenance: profiling, tracing, monitoring
- Aspects and JMX are the perfect solution
Basic Tool Set
Why do we need tools? To reduce the compile/deploy/test life-cycle. This is live testing, not unit testing. Many ideas also support view creation, code completion in view pages and previewing.
What can you do without tools? Test, test and test some more. Unit and integration testing should be possible out-of-container.
First thing you should is get a good IDE! Rob recommends IDEA and used it for all his demos. Make sure your IDE has the following features:
- View creation support: JSP, Velocity, JSF
- App server integration: Tomcat, Jetty, WebLogic, WebSphere; deploy/debug from the IDE
- Good candidates: IntelliJ IDEA, Eclipse with WTP/MyEclipse or NetBeans
- Webapp aware - so you can simply click "run" to view it in a browser
Jetty is your friend! It allows you to rapidly deploy, it's resilient to hot deploy, starts everything in about 2 seconds and integrates with everything.
Maven is your other friend. It allows you to kick-start a web project very easily. It also has Jetty integration that allows you to hot deploy. The Jetty plugin also detects changes and redeploys automatically. It even creates project files for IDEA and Eclipse.
Caveats with Maven: Its online repositories are full of junk: many different versions of POMs. To solve this, use mvnrepository.com to browse and find the right JARs. Also, lots of things are missing from the central repo: Trying finding a full Jamon distro.
Solution: Get your own in-house repo (easy to manage, overcome missing dependency woes).
Now Rob is doing a Maven QuickStart demo. He's using the maven-archetype-webapp to create a web application with Maven. He then added the Jetty Plugin and showed how it's easy to get started. For those of you that aren't aware, there's also a Tomcat Maven Plugin that allows you to use Tomcat instead of Jetty. There's also a debate ensuing on whether Cargo should have this functionality or whether these plugins are better. I'm currently leaning towards the plugins since their easier to setup and configure (and they work too!).
Accelerating Spring MVC Development
- Important existing features: testing outside the container and controller infrastructure
- Important new features in Spring 2.0: code by convention, JSP form tags, quick prototype with dynamic languages
Spring has many different Controller options: Controller/AbstractController, MultiActionController and SimpleFormController/AbstractWizardFormController.
All of these can be tested outside the container. Unfortunately, SFC and AWFC are not so simple to test.
Rob recommends using with Controller and MultiActionController and using Web Flow for most other things.
The fact that Rob doesn't recommend using SimpleFormController is quite interesting. I've never liked that I have to use Controllers for displaying data and SimpleFormController for forms, and apparently the Spring guys don't either. Rob says that if you're new to Spring MVC, it's better to skip learning/using SFC and use Web Flow instead.
Testing outside of the container is one of the best things in Spring MVC (I agree). Spring Mock provides the necessary infrastructure with MockHttpServletRequest and MockHttpServletResponse. The most value can be gained from transaction integration in tests (using my favorite class - AbstractTransactionalDataSourceSpringContextTests). Mock test are useful to test error conditions and hard-to-reproduce conditions, but integration tests are better in the web tier.
Code by convention: Spring 2.0 introduces many Code by Convention features: view names, model parameter names, URL mappings. This reduces duplication and increases uniformity.
JSP form tags: Creating forms in Spring 1.* was painful. The <spring:bind> tags were verbose and unclear. Spring 2.0 introduces new <form:*/> tags. These tags are much easier to read and write. They clearly express the intent and handle all the common cases such as binding and error handling.
Dynamic Languages: Spring 2.0 introduces support for beans written in other languages: JRuby, Groovy and BeanShell. These are just plain beans: inject into them, advise them and expose them via JMX. Change detection is built in (see live changes). Difficult integration is taken care of. For example, how do you call methods in a dynamic object from Java.
Now Rob is doing a demo of developing with Spring MVC and using CoC.
One of the new things in MultiActionController is you don't have to return ModelAndView - you can return Map or have void methods as well.
The ControllerClassNameHandlerMapping is a new class in Spring 2.0 that figures out the URLs for you based on Controller names. If you're using a MultiActionController, the URL is the first part of the name and anything after it, for example: /catalog/*. By configuring an additional property, you can make * map to method names. For regular Controllers, the mapping doesn't have the trailing slash (i.e. /catalog.html).
Another new class in Spring 2.0 is ModelMap. This class figures out your model names based on the simple class name. Single objects are simply lowercased, whereas collections of objects are available as objectnameList (i.e. a Set of User objects will be userList).
A method in AbstractTransactionalDataSourceSpringContexts that's quite useful is countRowsInTable(tableName).
To debug from your IDE is generally pretty easy. If you setup your IDE to debug a "Remote Application", it'll tell you the parameters you need to start that application with. For example, to debug the Maven Jetty Plugin in IDEA, create a new Remote Application in IDEA (Run -> Edit Configurations -> Add -> Remote) and then copy the command line arguments (listed below as well) into your MAVEN_OPTS environment variable.
-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005
After doing this, you should be able to restart Jetty and set breakpoints in your IDE.
Now Rob is showing us a JRuby example, where he's writing a Controller in JRuby and changing it/refreshing it in his browser. The code looks fairly simple and the configuration (in his *-servlet.xml file) looks like the following:
<lang:jruby id="stocklistController" script-source="WEB-INF/script/StocklistController.rb" script-interfaces="org.springframework.web.servlet.mvc.Controller" ... />
Unfortunately, I didn't get a chance to write down the entire bean definition, but hopefully you get the idea.
Summary: Rapid Development with Spring MVC
- Use a project template: Build your own (simply create a ZIP file) or use Maven 2 archetypes.
- Make sure you can deploy quickly and frequently: Jetty is the way to go here.
- Build deployment into your build script: slapped wrists for using Tomcat Manager!
- Adhere to a code/test cycle: create mock tests to test error conditions. Use integration tests to verify end-to-end functionality.
- Code by Convention reduces repetition and increases uniformity.
- Dynamic languages: rapid prototyping, take advantage of additional language features
- JSP form tags: Largely replace <spring:bind/>
Exploiting Web Flow
What is Web Flow?
A component for defining and managing interactions with the user. Typically long-running interactions. Workflow for the web.
Integration with traditional MVC frameworks: Spring MVC and Struts. SWF was originally designed to work with Struts.
Why bother using Web Flow?
Productivity! It removes plumbing from your code: state management, flow management, allowed actions/security, isolation and concurrency. By removing this plumbing, it allows you to focus on the business code.
Key Components of SWF:
- Flow Definition: A definition of a process in the application. For example: checkout, register and CRUD.
- State: A single state in the execution of a flow.
- View State: A pause state that displays a view to the user and typically prompts for input.
- Action state: A stat that executes on or more actions and then moves to another state (where the logic happens).
- Decision state: a routing state, evaluates or or more expressions (against data in the various scopes) and routes to a given state.
- Action: The logic inside the Action state that gets executed.
- Event: The user signaled event (submit, cancel, process, etc.).
- Transaction: a movement from one state to another in response to some event.
The three configuration elements of Spring Web Flow are: Flow Executor, Flow Repository and Flow Registry.
One of Robs favorite things about Web Flow is the Testing support. SWF provides full testing support with AbstractXmlFlowExecutionTests. This class provides an API for you to start and stop the flow. It also allows you to override the
registerMockServices() method to register mock implementations of your services. You can also override
createFlowServiceLocator() to do integration testing. There are also a number of useful testing-related methods available on
AbstractXmlFlowExecutionTests to verify things are happening correctly within your flow execution. The
MockParameterMap makes it easy to set parameters to pass into the flow.
- SiteMesh: Apply site-wide formatting, use it in conjunction with a CSS Framework (Rob is using the same one that AppFuse does - Mike Stenhouse's CSS Framework).
- AspectJ: Great for adding in filtering, monitoring and profiling.
- Jamon: Great in conjunction with AspectJ.
- JMX: Adds in management functionality.
If you liked the ideas that Rob presented in this talk, don't miss my talk on Saturday night. AppFuse 2.0 will have most of these components and ideas built-in by default.
This was an excellent talk by Rob. I certainly enjoyed myself, which is likely obvious since I wrote almost everything down. ;-)