I wanted to use logback for my tests’ logging on an SBT project recently, and it took a little while to work out how best to do it. The good news is that it turns out to be simple enough (once you know what to do).
In your build.sbt add dependencies for Groovy and Logback Classic (I have restricted them just to ‘test’ scope as I only want this to apply to my tests)
“Watermelon reporting” is a lovely phrase I heard for the first time the other day.
Everything’s red in the centre of the organisation, gradually changing colour as you go up through the layers until it’s nice and bright green on the outside. Don’t worry boss, the reports are all looking good…
I have been looking at using jsr303 annotations to mark up some of my beans. The good news is that both Hibernate and Springplaynicely with these annotations, and will validate them at appropriate times. The bad news is that the examplesoftesting these annotations that I have found online so far look cumbersome and awkward.
Let’s take a simple example:
simple java bean with a single jsr303 annotation
12345678910
publicclassSimpleBean{@NotNullprivateLongid;privateStringname;publicSimpleBean(Longid,Stringname){this.id=id;this.name=name;}// getters and setters...}
This is fine so far and we have the possibility that the constructor could be passed a null id. So, let’s write a unit test that ensures our validation will barf.
And our new-look test spits out the following upon failure:
123
java.lang.AssertionError:
Expected: no jsr303 validation violations
but: was <[ConstraintViolationImpl{interpolatedMessage='may not be null', propertyPath=id, rootBeanClass=class com.example.SimpleBean, messageTemplate='{javax.validation.constraints.NotNull.message}'}]>
There. Much nicer. Not only do we know that the test failed, but we are immediately told how it failed.
Spring Security is a seriously useful tool but one of the things that has been nagging away at the back of my mind about it is that it is so heavily reliant on magic strings. Take a typical example:
This configures all URLs in the application to require that the user is logged in and has the privilege named ROLE_USER.
sensitive method
1234
@PreAuthorize("hasRole('ROLE_SYSADMIN')")publicStringgetSensitiveInformation(){return"Only special people are allowed to see this information";}
This ensures that anyone calling this method (either directly or indirectly) must be logged in and have the privilege named ROLE_SYSADMIN.
So far, so straightforward.
The problem is that these role names proliferate across the codebase. Chances are you will want to refer to the same role name in many different places in your application. If these role names were in code, you would typically refactor them out into a single representation as soon as you had two different references to them in the codebase. Unfortunately, this is not so simple with Spring Security.
@PreAuthorize("hasRole(T(com.example.Authority).SYSADMIN.toString())")publicStringgetSensitiveInformation(){return"Still only special people are allowed to see this information";}
Unfortunately IntelliJ Community Edition’s ‘Find Usages’ is not clever enough to return these Spring expression language references, but it does at least feel better than sprinkling identical magic strings across the codebase.
I have picked up some contracting work to build a new web site. It is very early days and I am just putting together some initial workable web forms at the moment and want something for editing information that would be a little less ugly than just presenting a standard set of populated html form controls. Instead, I like the idea that the information will be written to the page as normal text, but clicking on it will allow you to change the value inline. After a little poking about, there appear to be two main contenders to help implement this in JQuery, Jeditable and Editable.
Feature comparison of Jeditable and Editable JQuery plugins
Jeditable
Editable
html 5 form elements
no
no
extendable input types
yes, via inbuilt addInputType method
yes, by modifying the source directly
default POST data format
id:element_id value:element_value
none
Adding html5 input types
Editable
Editable does at least provide an editableFactory in its source which is intended to be extended. Although easy to do, it still doesn’t get around the fundamental problem of having to modify the source itself.
modifying .editableFactory directly to handle ‘url’ input types
12345678910111213141516171819202122
$.editableFactory={'text':{toEditable:function($this,options){$('<input/>').appendTo($this).val($this.data('editable.current'));},getValue:function($this,options){return$this.children().val();}},// adding custom support for <input type="url">'url':{toEditable:function($this,options){$('<input type="url"/>').appendTo($this).val($this.data('editable.current'));},getValue:function($this,options){return$this.children().val();}},// end of added block...
Jeditable
There really is not much in it in terms of complexity or verboseness between the two implementations, but the fact that Jeditable allows extensions without modifying its source swings it for me.
Extending Jeditable’s set of supported input types
Both of the following examples work with the following template. You will also notice that this is not plain html, but a velocity template. The template is served from a spring/velocity application, more details of which will follow in later posts.
So we wait for the document to be loaded by the browser, then decorate all elements with the “editableURL” class with Editable’s behaviour. The end function is triggered when you submit your change, and is responsible for POSTing the data back to the server. Note that, in this example, data is POSTed back to the same URL from which the page was served.
All in all, this is rather nice, and we have complete control over the data passed back to our server.
Jeditable
As mentioned in the comparison table above, Jeditable by default will POST data in the format id: element_id, value: element_value. This is fine for table-based data in which every field has an id, but a long way from OK for our domain-object-backed Spring application. The good news is that we get complete control over Jeditable’s POST behaviour, too.
This snippet works broadly the same way, with the added control that the return value of the function is what is used as the new value displayed on the page. I can’t make up my mind whether this is a good thing. As the script stands, if the server encounters an error updating the field, then the new value will be displayed on the page and the user will be none the wiser that anything went wrong.
Conclusion
Although Editable is arguably preferred by Stack Overflow users, there is a little snag with both of them. Neither library seems to handle keyboard navigation particularly well (at least in Chrome on OS X). Editable’s submit and cancel buttons do nothing when they are triggered by receiving focus and hitting the spacebar, whereas Jeditable’s support is better in that the buttons do work, just that you have to be quick about it. If you leave the focus on the button for more than a second or so then it assumes you have given up and cancels the edit, taking away the form control again.
All in all, Jeditable seems to suit my preferences a little better. Its public revision control and nicer web site also make it seem just that little bit more polished. The only negative point, and it is a small one, is that Jeditable doesn’t provide a labelled version number. Judging by the readme on github it is up to version 1.7.2 at the time of writing, so that is the number I inserted into the filename myself before using it.
<!DOCTYPE html><html><head><title>Inline editing forms with JQuery and Jeditable</title><script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"type="text/javascript"></script><script src="/{your_path_here}/jquery.jeditable-1.7.2.mini.js"type="text/javascript"></script></head><body> #springBind("myDomainObject.url")
<spanclass="editableURL">$status.value</span><script type="text/javascript">$.editable.addInputType('url',{element:function(settings,original){varinput=$('<input type="url">');$(this).append(input);return(input);}});</script><script type="text/javascript">$(document).ready(function(){$('.editableURL').editable(function(value,settings){$.post(window.location.href,{url:value});return(value);},{submit:'save',type:'url'});});</script></body></html>