Monthly Archives: July 2009

Meet The Experts – Agility on September, 4th

The first Meet the Experts – Performance took place in June and was a day to remember for all participants and organizers: new contacts were made, new insights and knowledge was gained, interesting discussions were happening – also food, drinks and atmosphere were great :) (See Slides & Pics from the event!)

The content of the second Meet the Experts is fixed and I am extremely happy, that we managed to gather the German-speaking experts also for the coming topic Agility:

  • Simon Roberts is freelancer agile software engineer and project manager, certified Scrum Master and registered PRINCE2 user. His engagements often consist of leading the first steps of an organisation towards agile software development. The connecting theme of his work is his passion to help organizations to find more effective ways for their software projects.
  • Boris Gloger was the first certified Scrum Trainer in Europe. Since 2004 he works as freelance Scrum consultant.
    After working for several European companies as project manager, team leader and head of software development (EDS, Broad Vision, ONE, Web.de), he decided to focus completely on Scrum.
  • Henning Wolf is managing director of it-agile in Hamburg. He has several years of experience from agile software projects (eXtreme Programming, Scrum, FDD) as developer, project manager and consultant. He published numerous articles and papers on agile software development and is author of the books “Software entwickeln mit eXtreme Programming” and “Agile Softwareentwicklung”. Henning Wolf helps companies and organizations to introduce agile methods.
  • Dietmar Strasser is Director of Quality Assurance in Borland’s largest development lab in Linz, Austria. He is integral part of the Silk development team since 12 years. As quality coach he is responsible for the continuous improvement of the software quality processes since 2008, supports the Scrum teams to introduce new features with highest quality with his domain knowledge, and is responsible for coordination with the enterprise quality centers in Signapur and .
  • Andreas Ebbert-Karroum is leading the competence center agility at codecentric. Since more than three years, he is certified Scrum Master. Since then he could apply his competencies in little and large (> 300 persons), internal and external, local and global projects as developer, Scrum Master or Product Owner. His focus at codecentric is the continuous improvement of the development processes in real projects, where technical, organizational and social capabilities give the challenging constraints to work in.

The pitch of the performance event was rather technical, much code examples and discussions covering unknown depths of the JVM. The agility event will be interesting on a completely different level. We will discuss how to pull through projects with agile methods, how those can be introduced in companies large and small and make them stick, and how that affects the teamwork. Additionally we offer a training to become “Certified Scrum Product Owner”. The Product Owner role is continuously tagged as the most difficult one to do right in Scrum, interestingly there are only few trainings available. So we are very happy that we could win Simon Robers as competent partner and expert for that training.

So this is the agenda for the Meet the Experts on Agility:

Certified Scrum Product Owner | 02.09.- 03.09.2009

Simon Roberts will explain to a limited set of participants (max 20 persons!), what makes a good Product Owner, and where are perils and pitfalls (and of course also how to avoid or handle them). He will cover important topics like: Agile Foundations, Product Vision and Backlog, Agile Estimations, User Stories, Release Planning, Controlling and Reporting, Scaling Scrum and Retrospectives. Details can be found on the Meet the Experts Homepage under Trainings, where you can immediatly register (training is in German!).

Meet the Experts – Agilität | 04.09.2009

The Meet the Experts will take place like last time, with first-class setup, sessions and an open space to enable the participants to place topics, which are dear to their heart or currently aching in their project, but are missing on the agenda. The agenda from our experts is:

  1. Henning Wolf: Agile Methoden im Überblick: Scrum, XP, FDD, Kanban
  2. Andreas Ebbert-Karroum: Scrum Best Practices
  3. Boris Gloger: Going Large By Staying Small
  4. Dietmar Strasser: Agile Transformation aus Sicht eines QS Managers
  5. Simon Roberts: Making Scrum Stick: Sustainable Enterprise Transitions

Despite the English session titles, all talks will be held in German. The registration is enabled. I’m looking forward to that day and our guests. Maybe we even see the week before at the Agile 2009 conference in Chicago?

Andreas Ebbert-Karroum

 

Multiple select with Spring MVC

During our coding night (there’s be a separate blog for it), we committed ourselves to use only Spring technologies. But a simple requirement had a rather dramatic effect.

How do you create a multiple select box with Spring MVC? You should be able to select multiple elements, which then get added to a collection of the backing bean.

We are implementing a simple time tracking application. The domain model contains projects, which can have staff members assigned. Projects have tasks, which also have staff members assigned to. So in the task creation view we need a select box that contains all available employees.

Model

Here are the most important extracts from Tasks and Staff members:

Task

@Entity
public class Task implements Serializable {
	@Id
	@GeneratedValue
	private long id;
 
	@ManyToMany
	private Set<Staff> staffs = new HashSet<Staff>(0);
 
	//...
}

Staff

@NamedQuery(name = "staff.activeStaff", query = "select s from Staff s where s.disabled = false")
@Entity
@DiscriminatorValue("STAFF")
public class Staff extends Person {
 
	//...
}

Person

@NamedQuery(name = "person.findByUsername", query = "from Person p where p.login.username = :username")
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.STRING)
public abstract class Person implements Serializable {
 
	@Id
	@GeneratedValue
	private long id;
 
	//...
}

View

In the task creation view, we need a select box that shows all available employees. The selected employees shall then be assigned to the task when the form is submitted.

@Controller
@SessionAttributes("project")
public class ProjectController {
	@RequestMapping(method = RequestMethod.GET, value = "/project/createTask.action")
	public void createTaskView(@ModelAttribute Task task, Model model) {
		List<Staff> activeStaff = timetrackingService.getActiveStaff();
		model.addAttribute("activeStaff", activeStaff);
	}
 
	//...

The JSP that belongs to the controller contains this snippet for the select box:

<td><label for="staffs">Chose Staff: </label></td>
<td><form:select path="staffs" multiple="true" items="${activeStaff}" itemLabel="fullName" itemValue="id"/></td>
<td><form:errors path="staffs" /></td>

The problem is, as soon as you submit the form, you will get a ServletRequestBindingException, because Spring has no idea how to map a String (or String[] when multiple staff members have been selected) to a Set.

org.springframework.web.bind.ServletRequestBindingException: Errors binding onto object 'task'; nested exception is org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'task' on field 'staffs': rejected value [3]; codes [typeMismatch.task.staffs,typeMismatch.staffs,typeMismatch.java.util.Set,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [task.staffs,staffs]; arguments []; default message [staffs]]; default message [Failed to convert property value of type [java.lang.String] to required type [java.util.Set] for property 'staffs'; nested exception is java.lang.IllegalArgumentException: Cannot convert value of type [java.lang.String] to required type [de.codecentric.timetracking.model.Staff] for property 'staffs[0]': no matching editors or conversion strategy found]

Additionally, the generated HTML is missing the ID for staff members!

<select id="staffs" multiple="multiple" name="staffs">
<option value="">firstname lastname</option>
<option value="">aaaa aaaa</option>
<option value="">firstname lastName</option>
<option value="">firstname aaaa</option>
<option value="">firstname lastname</option>
</select>
<input type="hidden" value="1" name="_staffs"/>

Id as String

In order to have the staff member ID in the value attribute of the option element, we can create a new getter in the Person class that returns the id as String, and then use that in the JSP:

public abstract class Person implements Serializable {
	//...
	public String getIdAsString() {
		return new Long(id).toString();
	}
}
<form:select path="staffs" itemValue="idAsString" multiple="true" items="${activeStaff}" itemLabel="fullName"/>

InitBinder

The solution to the binding problem is more difficult. We need a PropertyEditor for the attribute ‘staffs’. Spring contains a number of PropertyEditors, so we can use the CustomCollectionEditor. It is expected that the property editor can map the string from options value back to the element, so we need to store that mapping somewhere, in a map for example.

public class ProjectController {
 
private Map<String, Staff> staffCache;
 
@RequestMapping(method = RequestMethod.GET, value = "/project/createTask.action")
public void createTaskView(@ModelAttribute Task task, Model model) {
	List<Staff> activeStaff = timetrackingService.getActiveStaff();
	staffCache = new HashMap<String, Staff>();
	for (Staff staff : activeStaff) {
		staffCache.put(staff.getIdAsString(), staff);
	}
	model.addAttribute("activeStaff", activeStaff);
}
 
@InitBinder
protected void initBinder(WebDataBinder binder) throws Exception {
	binder.registerCustomEditor(Set.class, "staffs", new CustomCollectionEditor(Set.class) {
		protected Object convertElement(Object element) {
			if (element instanceof Staff) {
				System.out.println("Converting from Staff to Staff: " + element);
				return element;
			}
			if (element instanceof String) {
				Staff staff = staffCache.get(element);
				System.out.println("Looking up staff for id " + element + ": " + staff);
				return staff;
			}
			System.out.println("Don't know what to do with: " + element);
			return null;
		}
	});
}

The code still contains some debug output to System.out, which has to be removed. But it shows that the method is called very frequently. Only for showing the select box with 5 employees, the method is caller 15 times. 10 times the id is passed in as a String, and 5 times the object is passed in. I have found no good documentation what exact behaviour is expected from that PropertyEditor, this is the best working solution I could come up with.

Looking up staff for id 1: Staff(firstname lastname)
Looking up staff for id 1: Staff(firstname lastname)
Converting from Staff to Staff: Staff(firstname lastname)
Looking up staff for id 2: Staff(aaaa aaaa)
Looking up staff for id 2: Staff(aaaa aaaa)
Converting from Staff to Staff: Staff(aaaa aaaa)
Looking up staff for id 3: Staff(firstname lastName)
Looking up staff for id 3: Staff(firstname lastName)
Converting from Staff to Staff: Staff(firstname lastName)
Looking up staff for id 4: Staff(firstname aaaa)
Looking up staff for id 4: Staff(firstname aaaa)
Converting from Staff to Staff: Staff(firstname aaaa)
Looking up staff for id 5: Staff(firstname lastname)
Looking up staff for id 5: Staff(firstname lastname)
Converting from Staff to Staff: Staff(firstname lastname)

After selecting an employee and submitting the form, expectedly there’s only one line in the log, converting the id back to the staff member.:

Looking up staff for id 3: Staff(firstname lastName)

Conclusion

With the massive amount of web frameworks around, I find it surprisingly complicated to achieve something as simple as a multiple select box in Spring MVC. But, I just leard Spring MVC yesterday, so I might not know all details yet. So if there’s a more elegant and simpler solution to achieve the same as described above, I very much welcome your feedback.

Andreas Ebbert-Karroum

 

© 2010 codecentric