Wednesday, August 22, 2012

Various thoughts on web frameworks


Just a few thoughts I had in emails and wanted to record somewhere more public.

On upgrading from Struts 1 to Struts 2:

I’ve used both, but have never tried to migrate one to the other. Struts1 and Struts 2 and quite different – as you probably know. Struts2 was not an upgrade from the Struts1 codebase, but a completely different web framework (XWork or something?) that was rebranded as Struts2, so they work pretty differently. The only thing they really share is the name.

I think it is possible, and there seem to be guides around that can help. But I wouldn’t want to do it hehe. Struts1 is pretty ancient now though, I’d hate to be doing any new work in it. Struts2 at least has support for more modern stuff (JSON, ajax, web services etc) but I’m not a fan of Struts2 either – the whole stateful action thing just seems like completely the wrong way to do things, not only from just a Java standpoint (yes you know I’m a functional programming nerd), but ESPECIALLY for a web framework, where you’re fighting against the stateless nature of the web the whole time instead of working with it. Plus Struts2 kind of encourages you to use JSP which is probably the worst thing ever invented for the web. End rant.

Yeah I think you’re in for some pain, but it might be worth it if the old stuff really is worth keeping. I wouldn’t like to leave the old stuff in Struts 1 and have to get two different web frameworks to work together. 

On what's wrong with JSP:

The main issues I have with JSP is the nebulousness of it, and the ugly confusing syntax. 

JSPs are compiled to Servlets, and your actions or controllers are servlets so what goes where? It’s an arbitrary decision, and you have to be very disciplined to keep that line clear. And in a team of developers it’s just not practical – you end up with business logic in the view code, and view code in the business logic. Everything becomes a big ball of mess. At least with something like Freemarker or Velocity, the template can ONLY be used as a view (mostly), so it is much easier to keep things tidy and organised, and for people to understand what should go where. Also JSP syntax just can’t compete any more with more modern templating languages.

I used JSPX for a few years on a  project... The idea sounds good and it gives you a bit of that separation, but I didn’t find that much benefit – why would you want your view code to be all XML? XML is horrible! :) Modern IDE’s can cope with JSP or other templating languages just as well and it was a bit annoying to have to keep escaping with CDATA sections.

If you’re using Spring MVC, Freemarker is probably a pretty good choice  - it has all the equivalent Spring MVC macros that they wrote for the JSP taglibs and is much, much nicer to use than JSP.

But take all my recommendations with a grain of salt, because I dislike the whole idea of server-side templating of HTML to start with. I’ve written a few posts in the past about what I dislike about it like this one and this one and in the past few years things have come a long way. 

It’s now not only possible, but preferable to use minimal server-side templating. You can expose data as JSON web services, write your views in plain old HTML and Javascript, and use client-side templating if necessary. This way you’re working with the architecture of the web, instead of against it. I know that is all too revolutionary for the suit-wearing types, but to me the idea that it’s the server’s responsibility to generate a view on each request based on view templates on the server side to be interpreted and executed on a client side browser just seems like madness when the browser is perfectly capable of doing it.


On getting started with Freemarker and Spring MVC:

You’ll be fine with Freemarker and Spring MVC, it’s a well known and well supported combo. It’ll be fun to learn, and it genuinely is better than JSP. The concepts are not that different to what you would have done in JSP. Just remember that there is no magic, Freemarker is just a really dumb (but powerful) macro language that will spit out text (which happens to be html in this case). And that is its beauty. Spring has written their own freemarker macros which you can use, but again there is no magic in them, they are just spitting out html that will nicely work with your Spring MVC Controllers, you can look at the macros to see what they are doing. Make sure you get a good Eclipse (sigh) Freemarker plugin ;)

I’m sure you’ve seen it, but the spring docs are good to help get set up: http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/view.html#view-velocity

To learn the freemarker syntax, the beginner’s guide is worth reading: http://freemarker.sourceforge.net/docs/dgui_quickstart.html

And this page is a good reference once you get into it: http://freemarker.sourceforge.net/docs/ref.html  And hopefully the eclipse freemarker plugin helps out a bit too. But yeah it’s always good to look at some real working code – maybe cruise around github or see if you can find a freemarker/Spring demo project somewhere.

One little trick I would recommend: Freemarker supports an alternative syntax, basically square brackets instead of angle brackets. It can make it a little bit visually nicer to read on the .ftl pages (especially in Eclipse), having square brackets for Freemarker code, and leaving angle brackets for the HTML code. This page explains it:http://freemarker.sourceforge.net/docs/dgui_misc_alternativesyntax.html You don’t need to put the [#ftl] on every page like the link says, you can just set a switch in your web.xml once. I think it's “setTagSyntax” or something.

Thursday, June 7, 2012

How to test functions in Dojo JavaScript modules with Jasmine and Maven


I almost gave up on this, but finally got it working.

Firstly, you need to override dojoConfig, like it describes in this article

Secondly, the jasmine-maven-plugin does not seem to handle resources outside of the jsSrcDir. I was trying to do things like this:

${basedir}/src/main/webapp/library

    ../jasmineTestBootstrap.js
    ../dojo-1.7.2/dojo/dojo.js
    */*.js
    */*.coffee


But trying to access includes which are outside the src dir (using ../) doesn't seem to be possible.

Apart from that everything seems to work ok, and it is MUCH nicer than Dojo Objective Harness (DOH indeed) My final configuration looks like this:

${basedir}/src/main/webapp/library

  mystuff/custom/jasmineTestBootstrap.js
  dojo-1.7.2/dojo/dojo.js
  mystuff/*/*.js
  mystuff/*/*.coffee


jasmineTestBootstrap.js looks like this:

dojoConfig = {
  modulePaths: {'mystuff': '../../mystuff'},
  isDebug: false,
  parseOnLoad: true
};

Thursday, April 12, 2012

JUnit @Ignore considered harmful


Let's listen in to what happens when Joe Developer uses a JUnit @Ignore annotation...


50% chance

"Hmm a test is breaking."
"I'll just add an @Ignore so the build goes green again, and doesn't interrupt anyone."
time passes
"Oh I can't figure this out. The build is green, I'll just leave it, nobody will notice."

35% chance

"Hmm a test is breaking."
"I'll just add an @Ignore so the build goes green again, and doesn't interrupt anyone."
gets distracted by something else, forgets about fixing the test

10% chance

"Hmm a test is breaking."
"I'll just add an @Ignore so the build goes green again, and doesn't interrupt anyone."
time passes
"That was an easy fix."
fixes the test, but forgets to remove the @Ignore tag

5% chance

"Hmm a test is breaking."
"I'll just add an @Ignore so the build goes green again, and doesn't interrupt anyone."
time passes
"That was an easy fix."
fixes the test, and correctly removes the @Ignore tag

Solution

Don't use JUnit @Ignore tags. Use something like this instead, which allows you to ignore the test temporarily.

Thursday, August 25, 2011

@Nullable / @Null / @NotNull / @Notnull / @Nonnull / @CheckForNull annotations


Jetbrains never ceases to delight. As of 10.5, their IDE supports not only their own pioneering org.jetbrains.annotations Nullable annotations, but also any other arbitrary @Nullable annotations you decide to use.

Currently the most popular ones are the JSR-305 (javax.annotation) annotations, the FindBugs nullable annotations, and IntelliJ's own nullable annotations.

If you decide to use the Findbugs annotations (which are found in package edu.umd.cs.findbugs.annotations), keep in mind that you probably want to use @CheckForNull instead of @Nullable. By default IntelliJ includes @Nullable for Findbugs, but you should change that to @CheckForNull.

The reason is that @Nullable is all but ignored by Findbugs if you decide to use that as well. Findbugs' annotations seem badly named, but hey that's just the way it is.

On a related subject, be careful not to get the JSR-303 nullable annotations confused with the JSR-305 nullable annotations.

Here is a quick summary of the differences:

JSR-303

  • Used for runtime bean validation, NOT static code analysis
  • javax.validation.constraints.NotNull
  • javax.validation.constraints.Null


JSR-305

  • Used for Static code analysis - seems to be all but dead
  • javax.annotation.Nonnull
  • javax.annotation.Nullable


Findbugs

  • Used by the Findbugs static code analysis tool
  • edu.umd.cs.findbugs.annotations.NonNull
  • edu.umd.cs.findbugs.annotations.Nullable (Probably not what you want)
  • edu.umd.cs.findbugs.annotations.CheckForNull


IntelliJ

  • Used by IntelliJ IDEA, but also publicly available as a jar
  • org.jetbrains.annotations.Nullable
  • org.jetbrains.annotations.NonNull



As usual, IntelliJ's built-in IDE support for nullable is awesome, and Eclipse's is decidedly un-awesome.


Wednesday, June 22, 2011

FileNotFoundException when running a unit test in IntelliJ

If you are running a unit test in IntelliJ that needs to load a test file, you might come across this error.
java.io.FileNotFoundException: src\test\resources\testFile.xml (The system cannot find the path specified)
The problem may be that by default, IntelliJ sets the working directory to be the project root. If you are working on a maven project or something else with a complicated project structure, then you probably want it to look instead at the module root.

This is easy enough to configure. Simply go to:

Edit Configurations -> Defaults -> JUnit -> Working Directory

Set this value to $MODULE_DIR$ and you are done!

Also remember to delete any existing JUnit configurations so that it will pick up the default you have just set.

Friday, May 27, 2011

Spring Validation is still pretty dumb

HOW IT USED TO BE

One of the annoying things about Spring MVC 2.5 was the validation. Even Spring themselves have acknowledged it:

"In previous versions it was up to the developer to manually invoke validation logic"

HOW IT IS NOW

When Spring 3 rolled around, I was looking forward to some clever validator improvements. And Spring delivered!

You no longer have to manually invoke validators, but you can use the JSR-303 @Valid annotation to AUTOMAGICALLY invoke validation on the bean in your controller. Check it out below:

 @Controller  
 public class MyController {  
   @InitBinder  
   protected void initBinder(WebDataBinder binder) {  
     binder.setValidator(new FooValidator());  
   }  
   @RequestMapping("/foo", method=RequestMethod.POST)  
   public void processFoo(@Valid Foo foo) { ... }  
 }  

Awesome sauce!

WHY IT IS STILL DUMB

Yeah that's cool and all, but that's pretty much all they've done in the way of magic. When it comes to CONFIGURING validators (which is one place we could really use some magic), Spring Validation is still pretty stoopid.

You basically have two options - manually set the validator in your initBinder() (like you can see in the example above), or call setValidator (Validator) on the global WebBindingInitializer. Which looks ike this in the applicationContext.xml:

 <mvc:annotation-driven validator="globalValidator"/>  

This is pretty dumb too - having a single global validator for all models probably isn't very useful.

WHY IT IS NOT NORMALLY A PROBLEM

Now all of this isn't so bad when using Spring Validation with Spring MVC. Normally We have one Model per Controller, which is configured with one Validator (and incidentally one View - which is why it is called (yes you guessed it) MVC ).

So configuring a validator for a controller isn't too bad - we're already configuring the model and view for the contrller, so one more thing is not a problem.

WHEN IT IS A PROBLEM

It becomes a problem when you want to use it OUTSIDE of the MVC framework. When you don't have a controller to configure your validator and model to - how on earth do you wire this stuff up?

Suppose I have an arbitrary model that I want validated with Spring's framework - how do I do it? I don't need any of Spring's Binding facilities. And nothing magical like this seems to exist:

 @Autowired MagicalSpringValidationMonkey magicalSpringValidationMonkey;  
 public void myService(MyModel myModel){  
   Errors errors = magicalSpringValidationMonkey.validate(myModel);  
 }  

I would expect my Magical Spring validator to do three things:
1. Run any JSR-303 Bean Validation configured for the model
2. Find and run the appropriately configured Spring Validator for this model
3. Return me an errors instance containing all of those errors.


WHY IT SHOULDN'T BE A PROBLEM

JSR-303 Validation is configured on the model itself, so Spring should be able to figure out how to run that validation.

Spring Validators (my custom validation classes that implement Spring's Validator interface) are already configured to show which models they support, by means of the supports(Class clazz) method which must be implemented.

HMMM COME TO THINK OF IT

Actually now that I think about it, you know what? After writing this long rant, I figured out that it probably wouldn't be too hard for me to write the MagicalSpringValidationMonkey myself.

But you know what else? I'm annoyed that this isn't already there, and that I had to do so much investigation to find out how it works, so I'm not gonna do it. Plus I'm too lazy. And Margaret River is calling me.

I hope you enjoyed this rant.

The end.

Tuesday, December 14, 2010

Something I didn't (and still don't) know about SQL

Take this simple Database Table:

Field1
(null)
abc
xyz

Here's a test for you. What will the following query return?

select * from table1 where field1 like 'a%'

If you answered abc you are correct - congratulations!
Ok now here is the same query slightly modified - what will it return:

select * from table1 where not (field1 like 'a%')

Surprisingly (to me) it doesn't return (null) and xyz, it only returns xyz. If anyone knows why can you please explain in the comments?