Saturday, September 21, 2013

Tree View using Knockout.JS

Recently I tried out various Javascript frameworks, among them Knockout.js. What I found most impressive was how easy it was to build a tree view using Knockout. All you have to do is create a template that calls itself for rendering the child nodes:
<script type="text/html" id="tree-node">
    <li>
        <i data-bind="css: {'icon-collapse-alt': expanded, 'icon-expand-alt': collapsed}, click: toggle"></i>
        <span data-bind="text: name, click: $root.selected"></span>

        <div data-bind="if: expanded">
            <ul data-bind="template: {name: 'tree-node', foreach: children}"></ul>
        </div>
    </li>
</script>
Then you place the tree view in your HTML like this:
<ul data-bind="template: {name: 'tree-node', data: root}"></ul>
And of course you need a view model for the tree:

  function TreeNode(values) {
      var self = this;
      ko.mapping.fromJS(values, { children: { create: createNode }}, this);
      this.expanded = ko.observable(false);
      this.collapsed = ko.computed(function() {
      return !self.expanded();
    })
  }
  
  TreeNode.prototype.toggle = function () {
      this.expanded(!this.expanded());
  };
  
  function createNode(options) {
      return new TreeNode(options.data);
  }
  
  var root = new TreeNode({ id: "1", name: "Root", children: [
      { id: "1.1", name: "Node 1", children: [
          {id: "1.1.1", name: "Node 1.1", children: []},
          {id: "1.1.2", name: "Node 1.2", children: []}
      ]},
      { id: "1.2", name: "Node 2", children: []}
  ]});
  
  var viewModel = {
      root: root,
      selected: ko.observable()
  };
  
  ko.applyBindings(viewModel, $('html')[0]);
You can try this example live in this Plunkr.

Thursday, October 6, 2011

TDD and Android

Today I stumbled upon this post by Adam Goucher in which he laments the lack of support for TDD for Android. I've got to say I whole-heartedly agree with his points, especially the part where he complains about the way most Android books either ignore testing completely or treat it as an afterthought.

For my own Android development I have tried the approach of dividing the application into an Android independent part which I test using regular Java unit tests and an Android dependent part which I currently test the old-fashioned way, i.e. running the app on a real smartphone and watching the logcat output. For my simple app that works quite well but it's only halfway reliable because manual tests are obviously rather boring so I tend to test only the parts I've actively changed instead of doing a full test after each change.

But at least the automated tests cover most of the inner workings of the app which is a big step in the right direction and has enabled me to add features more quickly and reliably than I could before.

Saturday, July 16, 2011

Four months on the Market

It's been almost four months since I opened my developer's account on the Android market and published my first app. Much to my amazement that app is not only constantly downloaded by someone but a significant part of the downloaders find it useful (or harmless) enough to keep it. In fact the number of downloads just broke the 500 mark. So what did I learn from this experiment?

Thursday, May 19, 2011

Spring MVC: Mixing annotation based and classic controllers

One of the improvements in Spring MVC 3 was a nifty namespace simplifying the configuration. If you're starting a new project and want to use the default setup your MVC setup pretty much fits on a napkin:
<beans>
  <mvc:annotation-driven />
  <context:annotation-driven />
  <bean:component-scan base-package="org.acm.steidinger"/>
  <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
    <property name="prefix" value="/WEB-INF/jsp/"/>
    <property name="suffix" value=".jsp"/>
  </bean>
</beans>


Now I don’t know about you but I rarely have the pleasure to start a project with a clean slate. And if you already have an application which uses the old style of Spring MVC controllers, too many of them to port them to the new style overnight, you’ll have to have a setup which enables you to use the old and the new in parallel. In that case you can't use the namespace configuration and have to setup your MVC config explicitly.



Unfortunately the reference documentation leaves you on your own. There is no example for this kind of config and neither is there an explanation what <mvc:annotation-driven /> actually does. Of course there is always the source code, but it takes a bit of time to find out what exactly is going on. So I recently took the time to analyze the setup and here is my MVC configuration which allows me to mix annotation based controllers and validators with inheritance based controllers and validators:



<beans>
  <context:annotation-driven/>
  <bean:component-scan base-package="org.acm.steidinger"/>

  <bean id="localValidator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
  <bean id="annotationHandlerMapping" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
  <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean" />
  <bean id="methodHandlerAdapter" class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
    <property name="webBindingInitializer">
      <bean class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
        <property name="validator" ref="localValidator" />
        <property name="conversionService" ref="conversionService" />
      </bean>
    </property>
  </bean>

  <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    <property name="mappings">
      <props>
        <prop key="/classic.htm">classicController</prop>
      </props>
    </property>
  </bean>
  <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
  <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <property name="basename" value="/WEB-INF/messages" />
  </bean>
  <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
    <property name="prefix" value="/WEB-INF/jsp/"/>
    <property name="suffix" value=".jsp"/>
  </bean>

  <bean id="classicController" class="org.acm.steidinger.springExample.web.ClassicController">
    <property name="commandName" value="form" />
    <property name="formView" value="test" />
    <property name="successView" value="test" />
    <property name="validator">
      <bean class="org.acm.steidinger.springExample.web.ClassicFormValidator" />
    </property>
  </bean>
</beans>


The example above contains the beans necessary to setup the infrastructure as well as a single old style controller.  Pretty straightforward. The only part that was a bit tricky was the AnnotationMethodHandlerAdapter. For JSR 303 aka Bean Validation to work you need to configure the AnnotationMethodHandlerAdapter’s webBindingInitializer with a reference to the validator and conversionService. Otherwise everything will seem to be working but the validation will not work.

Sunday, March 20, 2011

Fooling around with Android

This weekend I finally found the time to dabble with Android development, something I'd planned for quite a while now. Since I'm a fan of Locale, which allows you to change various phone settings based on e.g. your location, I decided to try to write a plugin for Locale. There is already a plugin which lets you silence your phone whenever your calendar shows an appointment but I found that it doesn't work with older Android versions (Too bad my phone only runs Android 1.5.) So this was to be my first Android project...

The first obstacle was that Android doesn't have an official API to get at the calendar data stored on the phone and I really didn't want to hit the net every few minutes. Luckily Jim Blackler has an excellent blog post showing how to access the calendar on your phone, so that problem was solved quickly.
Another invaluable resource was the developer documentation and example plugin provided by Locale's developers, two forty four a.m. LLC.. A few hours later I actually had the first working version of the plugin on my phone (see screenshots).

It's still far from perfect, e.g. I fear it sucks the battery empty much faster than I'd like. Nevertheless I found it quite exciting how easy it was to get so far. If you're interested in the source code you can find it on Github but please bear in mind that it is still quite unpolished. You certainly won't find any clever tricks in there ;-) But unlike that other plugin (for which I paid, BTW), this one at least works...

Sunday, April 18, 2010

Don't expect too much from your ORM tool

Last week I found a strange bug in a project I’m working on. We have a couple of domain objects which depend on each other in a multi-level master-detail relation. The domain objects are managed by Hibernate and everything was working fine until we noticed that sometimes after a complicated update the details relation of one of the master objects was missing a few entries. It took little time to identify the service method where the bug had to happen. However when I stepped through the code in the debugger everything was fine – each object contained all the dependent objects that had to be there. Too bad that the database didn’t agree with the debugger.

Be careful with one-to-many relations

So what exactly was going wrong? The domain objects in question could have been taken clear out of a textbook, there was nothing special about them. But the effect is easy to reproduce even with two trivial classes.

The problem was that the same details object was added to two master objects. All was fine as long as the objects remained in the Hibernate session: the details object was contained in the corresponding Set of each master object. Of course the database saw things differently. There only one row in the master table could be the owner of the details row. And after the domain objects were reloaded from the database the object showed the same relation and only one master object owned the details object. The other “lost” it.

A trivial example

The code for a trivial example reproducing this effect looks like this:

Master.java

public class Master {
private Long id;
private String name;
private Set details = new HashSet();

public Master() {
}

public Master(String name) {
this.name = name;
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Set getDetails() {
return details;
}

public void setDetails(Set details) {
this.details = details;
}

public void add(Detail detail) {
this.details.add(detail);
}
@Override
public String toString() {
return "Master{" +
"id=" + id +
", name='" + name + '\'' +
", details=" + details +
'}';
}
}


Detail.java



public class Detail {
private Long id;
private String name;

public Detail() {
}

public Detail(String name) {
this.name = name;
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

@Override
public String toString() {
return "Detail{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}


Hibernate Mapping



<class name="Master" table="MASTER">
<id name="id" type="java.lang.Long">
<generator class="identity" />
</id>
<property name="name" type="java.lang.String" />
<set name="details" cascade="all" access="field">
<key column="MASTER_ID" />
<one-to-many class="org.acm.steidinger.masterDetail.Detail" />
</set>
</class>

<class name="Detail" table="DETAIL">
<id name="id" type="java.lang.Long">
<generator class="identity" />
</id>
<property name="name" type="java.lang.String" />
</class>


Test.java



public class Test {
public static void main(String[] args) {
Configuration config = new Configuration();
config.configure("hibernate.cfg.xml");
SessionFactory sessionFactory = config.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
Master firstMaster = new Master("first");
Detail detail = new Detail("firstDetail");
firstMaster.add(detail);
session.save(detail);
session.save(firstMaster);
transaction.commit();
transaction.begin();
Master secondMaster = new Master("second");
secondMaster.add(detail);
session.save(secondMaster);
transaction.commit();
System.out.println("firstMaster = " + firstMaster);
System.out.println("secondMaster = " + secondMaster);
session.clear();
transaction.begin();
firstMaster = (Master) session.get(Master.class, firstMaster.getId());
secondMaster = (Master) session.get(Master.class, secondMaster.getId());
System.out.println("firstMaster = " + firstMaster);
System.out.println("secondMaster = " + secondMaster);
transaction.commit();
session.close();
}
}


The session.clear() in the test method is there to simulate the following calls being in a new session. As you will see if you run this code the output will look like this:



firstMaster = Master{id=1, name='first', details=[Detail{id=1, name='firstDetail'}]}
secondMaster = Master{id=2, name='second', details=[Detail{id=1, name='firstDetail'}]}
firstMaster = Master{id=1, name='first', details=[]}
secondMaster = Master{id=2, name='second', details=[Detail{id=1, name='firstDetail'}]}


As expected one of the Master object loses the details object when it is reloaded from the database. But how can we avoid this effect? One way is to put the responsibility on the shoulders of the user of the domain classes who will have to be very careful about not adding an object to two owners. Another way is to augment the domain classes so that the details object can never have more than one owner.



A simple solution



Putting the responsibility on the user of our domain classes rather obviously is an invitation to disaster as sooner rather than later someone will forget the restriction. The first step to a solution is hiding the internals of the details relation, i.e. prevent an outsider from modifying the contains of the details set directly. To this end we modify the getter and setter as follows:



public Set getDetails() {
return Collections.unmodifiableSet(details);
}

public void setDetails(Set details) {
this.details = new HashSet();
for(Detail detail : details) {
add(detail);
}
}


Now the master object has complete control over what happens when a details object is added. It can detect if a newly added details object is already owned by another master or not. In our case the details object did not contain any special state and could be easily replicated so the proposed implementation for the add method looks like this:



public void add(Detail detail) {
if (detail != null && detail.getId() != null) {
this.details.add(new Detail(detail));
}
else {
details.add(detail);
}
}


Now if we run this new version of our example the output looks like this:



firstMaster = Master{id=1, name='first', details=[Detail{id=1, name='firstDetail'}]}
secondMaster = Master{id=2, name='second', details=[Detail{id=2, name='firstDetail'}]}
firstMaster = Master{id=1, name='first', details=[Detail{id=1, name='firstDetail'}]}
secondMaster = Master{id=2, name='second', details=[Detail{id=2, name='firstDetail'}]}


An obvious improvement to the above code is making the relation bidirectional and checking for an existing owner using the getter for the master object. However for this trivial example a quick check for the ID also works.



The moral of the story



Do not rely on your ORM tool for maintaining the correct semantics of your object’s relations. If you have objects that can only be owned by one owner ensure that restriction yourself.



I find it quite strange that none of the books on the topic of ORM that I’ve read fail to mention this pitfall.

Sunday, November 22, 2009

Enforcing method contracts with AspectJ and Spring EL

After reading a bit about the new Expression Language in Spring 3 I decided to try to use it to implement a very basic version of Design by Contract. I thought it would be nice to be able to specify pre and post conditions for methods in the expression language, e.g.

public class Stack {

@Require("value != null")
@Ensure("top().equals(value)")
public void push(String value) {
values.add(value);
}
}


It turned out that there were two problems with this approach:




  • The Spring EL saw the “value” and tried to find a matching property in the root object of the evaluation context. To access named variables you have to write “#value”. Not quite as aesthetically pleasing and a bit error prone, but easy enough.


  • The other problem was that there is no way to get at the parameter names using Java reflection of course. Luckily someone solved this problem for me. At codehaus there is this library Paranamer which will read the parameter names from the debug info in the class files.



So my annotations then looked like this:



public class Stack {

@Require("#value != null")
@Ensure("top().equals(#value)")
public void push(String value) {
values.add(value);
}
}


Enforcing the Contract



The annotation classes themselves are pretty boring, they only contain a value and specify that they only apply to methods and are retained at runtime.



@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Require {
public String value();
}


The fun part is evaluating these pre and post conditions.  It turned out that AspectJ makes it quite easy with its support for annotation based pointcuts:



public aspect ContractEnforcer {
pointcut methodWithPrecondition() : execution(@Require * *(..));
pointcut methodWithPostcondition() : execution(@Ensure * *(..));
pointcut methodWithContract() : methodWithPrecondition() || methodWithPostcondition();
ThreadLocal inContractCheck = new ThreadLocal();

Object around(): methodWithContract() {
if(Boolean.TRUE.equals(inContractCheck.get())) {
return proceed();
}
inContractCheck.set(Boolean.TRUE);
Object result = null;
try {
Signature sig = thisJoinPointStaticPart.getSignature();
if(sig instanceof MethodSignature) {
Method method = ((MethodSignature) sig).getMethod();
Paranamer paranamer = new BytecodeReadingParanamer();
String[] parameterNames = paranamer.lookupParameterNames(method);
Require precondition = method.getAnnotation(Require.class);
if(precondition != null) {
enforcePrecondition(precondition.value(), sig, parameterNames, thisJoinPoint.getArgs(), thisJoinPoint.getTarget());
}
result = proceed();
Ensure postcondition = method.getAnnotation(Ensure.class);
if(postcondition != null) {
enforcePostcondition(postcondition.value(),sig, parameterNames, thisJoinPoint.getArgs(), thisJoinPoint.getTarget(), result);
}
}
} finally {
inContractCheck.set(Boolean.FALSE);
}
return result;
}

private void enforcePrecondition(String condition, Signature signature, String[] parameterNames, Object[] parameterValues, Object target) {
if(!conditionSatisfied(condition, parameterNames, parameterValues, target, null)) {
throw new PreconditionViolationException(condition, signature.toString(), parameterNames, parameterValues);
}
}

private void enforcePostcondition(String condition, Signature signature, String[] parameterNames, Object[] parameterValues, Object target, Object methodResult) {
if(!conditionSatisfied(condition, parameterNames, parameterValues, target, methodResult)) {
throw new PostconditionViolationException(condition, signature.toString(), parameterNames, parameterValues, methodResult);
}
}
private boolean conditionSatisfied(String condition, String[] parameterNames, Object[] parameterValues, Object target, Object methodResult) {
try {
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression(condition);
EvaluationContext context = new StandardEvaluationContext(target);
for(int index = 0; index < parameterNames.length; index++) {
context.setVariable(parameterNames[index], parameterValues[index]);
}
context.setVariable("result", methodResult);
Boolean result = exp.getValue(context, Boolean.class);
if(result == null) return false;
return result;
} catch(ParameterNamesNotFoundException e) {
System.out.println("Could not check condition - parameter names not available");
} catch(ParseException e) {
System.out.println("Could not check condition: " + e);
} catch (EvaluationException e) {
System.out.println("Could not check condition: " + e);
}
return false;
}
}


So it turned out to be quite easy to provide this very basic contract enforcement. The ThreadLocal is in there to make it possible to use methods with contract annotations within the contract conditions of other methods. That way only the “top most” conditions are checked.



Of course there is a lot to be done but I think this approach looks quite promising. I expect Spring EL support to arrive pretty soon in most IDEs and then it probably won’t be too difficult to provide code completion and error checking for the pre and post conditions in the IDE.