Spring

From Elvanör's Technical Wiki
Revision as of 09:16, 10 September 2008 by Elvanor (talk | contribs)
Jump to navigation Jump to search

Spring is a JEE application framework. One of Spring main interest is to glue several components together, taking care of configuration and dependencies between those components. It also serves as a base framework for Grails.

Configuration

Web Deployment Descriptor Configuration

  • Due to the breaking of request path elements by the servlet container, it seems you cannot use a directory path mapping to Spring dispatcher servlet. Something like "/spring/*" is apparently not supported, since the servlet path is not what is expected by the dispatcher. Look here for more information.
  • A recommended configuration is either to use extension mapping (*.html) or map everything to the SpringDispatcher by using the "/" mapping. This prevents the use of the default servlet though, so be careful.

Configuring Beans

Hibernate session factory & Data Sources

  • The class to use to configure an Hibernate session factory is org.springframework.orm.hibernate3.LocalSessionFactoryBean. If you use Hibernate annotations, you must set configurationClass to "org.hibernate.cfg.AnnotationConfiguration". You can also use a subclass of LocalSessionFactoryBean to configure annotated classes (which allows you to not use an XML file at all, but configure everything through Spring).
  • The data source can of course be configured with Hibernate XML configuration, but it is recommended to configure it as a Spring bean and set the session factory dataSource property to it. This allows any Spring configured data source object to be used, not only Hibernate connection providers.

Controller Layer

Mapping requests to controller actions

  • If using annotations, your controller classes should not extend a base controller class like MultiActionController. As soon as you use the @Controller annotation, Spring correctly configures and recognizes your class as a controller. You also don't need to write a handleRequest() method; any action name can be used - see below.
  • If you use the recommended latest setup (annotations and CoC), you don't need to specify a mapping for the controller. You also don't need to specify @RequestMapping annotations for the actions in a multiaction controller. They will also be mapped by convention (although the mapping is actually done by a specific class, so you can customize this).
  • However you usually need to use an annotation for your controller actions in order to use whatever signature you want. If you don't, Spring recognizes as actions only the methods having a very specific signature, which is quite constraining. If you use an annotation, you can use whatever signature you need and powerful features such as binding of request parameters to method arguments. So usually you would just use:
@RequestMapping(method = RequestMethod.GET)
  • It does not seem very easy to map a default action for the URL "/controller/" (without any action name). There seems to be a bug in Spring, where if you have several actions the last one may be used as a default for all URLs not matched, but this does not happen all the time...

Transaction Support

  • It's important to be aware than for Spring managed transactions, rollback occur only if an unchecked exception is thrown. If a checked exception is thrown, the transaction does not rollback.

Locale Support

  • Spring supports different mechanisms for determining the current locale (the locale associated to the current thread). Grails uses the cookie mechanism (with a fallback to the HTTP request Accept-Language header).

Obtaining the current HTTPServletRequest

  • Obtaining this object in a domain object should generally considered as a bad practice, as it couples the object to an HTTP request. However this can be done using the following code (this works at least in Grails):
import org.springframework.web.context.request.RequestContextHolder as RCH
def request = RCH.currentRequestAttributes().currentRequest

Data Binding

  • Spring supports custom data binding for certain classes through the use of PropertyEditors.