"; */ ?>

spring


24
Jun 09

What is The Best Java Web Framework?

What is the best Java web framework

No, really, what is it? Are you one of those people who ever wondered why there is actually more than one? Or you work with Struts for 5 years in a row, and think it is the best, just because you know all the nasty hooks you have to implement to make it do what you actually need?

Are you one of those die hard Rails fans, who (as most of Rails developers) does not really know Java, but already has a lot to say how bad it is?

Do you work in C++, and feel absolutely confident, that the framework, your company had developed for the last 25 years, that build web pages via socket programming is the best, and the most efficient one out there?

Is your company big enough, so it has a mature team of software (what they call themselves) architects, that take open source frameworks, and write their own single wrapper framework around it that, as they think (since they wrote it), is the 8th wonder of the (ancient) world?

You, see, I am a consultant – I know many of you, since I met “you” before :)

This one will be a very short article about my experiences with several Java Web Frameworks out there. Here we go:

Spring MVC Would be a good choice for the most of your needs

(I’ll give a short controller example below)

Wicket Interesting to look at – no XML, no JSP (JSTL), just Java and HTML. Can mimic a flow in a WebPage object. Better separation of concerns than, for example, in GWT (e.g. no Javish CSS, etc.). Good Community

The only thing that is off is your dynamic HTML elements are done in Java

Spring Webflow Yes – it is a separate beast. It mostly is good, and makes sense, however, in practice, once you need to do something a bit more complex that a shopping cart or a hotel booking app (hint, hint), you can run into problems. “Back button” and “Double click” are not very well handled by the framework, may get an exception while bookmarking (there is a magic recipe, but far from being simple, and intuitive), sharing data across the flow, last resort error handling are not simple, etc.
Stripes Good / simple (no XML – conventions), but not very actively maintained – hence not as mature. (good community though) Worth to look at for simple projects.
Struts Just architected wrong from the very beginning: Validation (XML – why? What about minimum search criteria, what about several, what about nested OO validators!?) / 0 for NULLs / Multi Action Forms / Testing (without StrutsTestcase) / etc. ) Improved a bit since WebWork merging, but still lots of “code smells”.
JSF Quite hard to keep up with all these JSF based JSP tags + integration with security is not simple + full JSF solutions are usually Frankensteins with many pieces from different vendors.
Tapestry Not bad, actually make sense, when you get it. But have you ever looked and tried to follow the Tapestry code? – Very complex implementation, if ever need to look inside the code + Tapestry does take time to learn, so forget about a new off-shore team, or fresh out of college not so geeky grads, taking it on.

And here is why I like Spring MVC:

  • Binding / Validation is done just right – clean, testable, reusable
  • Multiple View options ( PDF, XML, Excel, Atom, etc… ) done easy [AbstractExcelView, AbstractFeedView, AbstractJExcelView, AbstractPdfView, AbstractUrlBasedView, AbstractXsltView ]
  • Annotation based – no XML madness, and very clear when looking at the code – check the Pet Clinic in Spring 3.0 M3
  • Integrates with Spring JS very nicely ( in case needed )
  • Handing requests and parameters with ( Spring ) expression language – quite flexible
  • In Spring 3, MVC is actually REST aware (GET, POST, PUT, DELETE)

You can download Spring STS, import sample projects, and see many examples on how to use it, but here is a very simple controller example from Spring’s Pet Clinic:

@Controller                                                 // it’s a controller
public class ClinicController {
 
      @RequestMapping("/welcome.do")           // that all there is to mapping
      public void welcomeHandler() {
      }
 
      /** @return a ModelMap with the model attributes for the view
                                 uses org.springframework.core.Conventions */
      @RequestMapping("/vets.do")
      public ModelMap vetsHandler() {
            return new ModelMap(this.clinic.getVets());
      }
 
      @RequestMapping("/owner.do")
      public ModelMap ownerHandler(@RequestParam("ownerId") int ownerId) {  // parameters are passed in easily
            return new ModelMap(this.clinic.loadOwner(ownerId));
      }
}

It all depends on project’s requirements / timeline / resources / requirements / technologies already in place / etc… But having a choice, I do choose Spring MVC – it just makes sense: easy implementaion with Spring Roo / integration with Spring’s back end / support / community / releases / etc… I also like where Wicket is going, but it feels like “it is still going…”

In any case – good luck, and remember – if it does not have to be Java, but you still like to “stay close”, I would definitely give Grails a shot.


19
Feb 09

Make Hibernate Update/Create Changed Objects

Make Hibernate Update/Create Changed Objects

While Hibernate is a mature framework it still has a a lot of room for improvement. Starting from polishing documentation: e.g. “MappingException JavaDoc: An exception that usually occurs at configuration time, rather than runtime, as a result of something screwy in the O-R mappings.“, and going towards more powerful default optimization.

In fact, Rod Johnson (leader of Spring Framework’s parenthood gang :)), and other SpringSource consultants, constantly mention that most of their time, on projects that use Hibernate, is spent fixing Hibernate optimization bugs.

A lot of people form their opinions on what characteristics of “a good software framework” are. There are books, articles about it, but people are different, so opinions vary. One of the characteristics that makes a good framework, in my opinion is “while allowing clients to hook into the internal framework code, do not encourage it”. Meaning the flexibility is there, but the framework should not encourage its clients to get inside framework’s stereotypes. This way framework’s code (internal stereotypes) can alter, and still have “older version clients” running without (significant) change.

One of such hooks that Hibernate actually encourages to use is evicting the object from the session.

Here is an example:

While reviewing one of a Spring Batch jobs, I found that under the same “transaction management roof” (HibernateTransactionManager) jdbcTemplate and hibernateTemplate behaved differently: jdbcTemplate updated records in DB, but hibernateTemplate was not even trying.

So I enabled Hibernate logging in “log4j.properties”:

log4j.rootLogger = ERROR, errorsLog
 
# Hibernate logs
log4j.logger.org.hibernate = DEBUG, hibernateLog
log4j.additivity.org.hibernate = false
 
# HIBERNATE APPENDER
log4j.appender.hibernateLog = org.apache.log4j.RollingFileAppender
log4j.appender.hibernateLog.File = ./path-to/hibernate.log
# Set the maximum log file size (use KB, MB or GB)
log4j.appender.hibernateLog.MaxFileSize = 4096KB
# Set the number of log files (0 means no backup files at all)
log4j.appender.hibernateLog.MaxBackupIndex = 10
# Append to the end of the file or overwrites the file at start.
log4j.appender.hibernateLog.Append = false
log4j.appender.hibernateLog.layout = org.apache.log4j.PatternLayout
log4j.appender.hibernateLog.layout.ConversionPattern = [%p] [%d{yyyy-MM-dd @ HH:mm:ss}] [%t|%c{1}] %m%n
 
# ERRORS APPENDER
log4j.appender.errorsLog = org.apache.log4j.RollingFileAppender
log4j.appender.errorsLog.File = ./path-to/hibernate-error.log
log4j.appender.errorsLog.MaxFileSize = 4096KB
log4j.appender.errorsLog.MaxBackupIndex = 1
log4j.appender.errorsLog.layout = org.apache.log4j.PatternLayout
log4j.appender.errorsLog.layout.ConversionPattern = [%p] [%d{yyyy-MM-dd @ HH:mm:ss}] [%t|%c{1}] %m%n

First, I read an object via Hibernate, update it in the code, and then call a dao’s update method to persist it – pretty simple. However while debugging it step by step, after executing the Hibernate update query, in a log, I saw:

[DEBUG] [main|DefaultSaveOrUpdateEventListener] ignoring persistent instance
[DEBUG] [main|DefaultSaveOrUpdateEventListener] object already associated with session: [EntityName#3]

So the Hibernate did not update the object due the fact that it thought that another object was already associated with this Hibernate session. Which, in fact, was the same reference to the same object, only the update was called from a different instance.

The solution to this was to evict the object from the Hibernate session right after reading it:

  ObjectDto objectDto = dao.findById( id );
  dao.getHibernateTemplate().evict( objectDto )

Once the fix was applied, after Hibernate update call, I saw:

[DEBUG] [main|DefaultEvictEventListener] evicting [EntityName]
[DEBUG] [main|DefaultSaveOrUpdateEventListener] updating detached instance
[DEBUG] [main|DefaultSaveOrUpdateEventListener] updating [EntityName#3]
[DEBUG] [main|DefaultSaveOrUpdateEventListener] updating [EntityName#3]

And the object was successfully persisted into the database.

Happy ORMing!


9
Jul 08

Spring Web Application Context Visibility

spring framework logoWhile developing a Web App using Spring little things can take a lot of time to resolve. At the end they may appear to be very simple, and you may ask your self “how could I not think of it before – it is so obvious!”. Well, yea, it is obvious, but you just have to know it! One of the places that helps you to solve the “obvious” (and not so obvious), so you do not have to spin your wheels is, with no doubts, the spring forum. However you need to know the right search criteria to find what you need.

Here I just want to share something small but important about the visibility of Spring Contexts in a Web App.

Looking at org.springframework.web.servlet.DispatcherServlet API notice this:

“A web application can define any number of DispatcherServlets. Each servlet will operate in its own namespace, loading its own application context with mappings, handlers, etc. Only the root application context as loaded by ContextLoaderListener, if any, will be shared.”

This brings an interesting point – in a Spring Web App you have one root application context which is private, and many dispatcher servlet application contexts which are children of the root application context:

<context-param>
<param-name>contextConfigLocation</param-name>
   <param-value>
      /WEB-INF/classes/applicationContext.xml
      /WEB-INF/classes/otherContext.xml
   </param-value>
 </context-param>
 
...
 
 <servlet>
  <servlet-name>context</servlet-name>
  <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
  <load-on-startup>1</load-on-startup>
 </servlet>
 
...
 
 <servlet>
  <servlet-name>dispatcher-servlet-number-x</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  <load-on-startup>2</load-on-startup>
 </servlet>

In the above, everything that is defined in “contextConfigLocation” is your root application context. Every “dispatcher-servlet-number-x” (“dispatcher-servlet-number-1”, “dispatcher-servlet-number-2”, etc..) would represent a child application context which will see (have the visibility to) all the beans from the parent (root) context, but will not see any of the beans defined by its siblings – another dispatcher servlet contexts.

The only gotcha in the above visibility is BeanFactoryPostProcessor / BeanPostProcessor (s) – like “PropertyPlaceholderConfigurer” for example. These guys apply ONLY to beans in its own context. For example, if you have PropertyPlaceholderConfigurer defined in the root application context, none of root’s children will be able to use it (see) the ${properties}.

Here is the semi-official version “why” from Juergen (Spring Lead Developer):

“PropertyPlaceholderConfigurer is an implementation of the BeanFactoryPostProcessor interface: This interface and its sibling BeanPostProcessor just apply to the BeanFactory that defines them, that is, to the application context that defines them.

If you combine multiple config files into a single contextConfigLocation, a PropertyPlaceholderConfigurer defined in any of the files will apply to all of the files, because they are loaded into a single application context.

However, a DispatcherServlet has its own application context, just using the root web application context as parent. Therefore, it needs to define its own BeanFactoryPostProcessors and/or BeanPostProcessors, in this case its own PropertyPlaceholderConfigurer.”

Happy Springing!