Does Vaadin make sense with Spring MVC (or any other MVC like Struts2)

Hello guys,
This is my first post.

I am started development of intranet application.
Initially I started doing it using Spring Roo. Its really great.
But still JSP/HTML are pain and it is not needed for intranet application…

I stumble upon Vaadin. Its really great and easy.
I worked on Swing before. So Vaadin is like home to me. :bashful:

Anyways,
I am wondering whether using MVC Controller makes sense in Vaadin?
I am unable to see any possibility of that.

Cheers,

IMO in most cases separating call-backs (controller) to another class from UI initialization (view) is just not just worth the effort and would make the application logic harder to follow and modularize.

Instead I would recommend slicing your UI into small independent logical UI components that contain both the “controller” and “view” in one module and provide a clean API for connecting the “model”.

I disagree with Jonas opinion.

I am assuming that your application has a significant complexity and size, not just the usual demo-stuff.

So you want to use the MVC-pattern - great, I fully agree! This is always a good thing for separation of concerns.

I have a really long experience with writing and using MVC-Frameworks, and my strong advice is to always keep a kind of abstract perception to the views. Whether you use Vaadin, Swing, SWT, whatever… why should you change your way of implementing controllers? If your UI-components both contain controller- and view-logic, it will be hard to recognize the part “controller” and it’s responsibilities in it… and even worse: If you want to support more UI-systems than Vaadin you can’t easily keep and reuse your controller-logic.

Yes sure, it’s more effort at the beginning, but later you will have more modularity, clarity and flexibility.

Cheers,
Marco

@Marco
Okay,
I have used MVC in Swing/GWT/Web.

In Swing have to follow a pattern/practice of following MVC.

But, My question is does web MVC framework makes sense?? Is there anyway I can use Spring MCV/Struts2 ?

I don’t think so, It is possible or even needed.
Actually after using a bit of vaadin I am sure that Web MVC doesnt make sense.

Cheers,

I don’t believe you can/shall combine Vaadin with any MVC web frameworks. They are totally different paradigms.

Hello guys,

Well, I have the same felling than Marco, and I have some elements for discussing (not for a joust please).

The first impression is all examples in the site doesn’t work with models. Just with “primitive” types like String.

I take the example of TwiColumnSelectExample I have adapted by doing adjustments to Vaadin 6.1.5 (added 2 interfaces : IListModelProvider<T, U> and ILabelProvider, rewritten TwinColSelect<T, U>) :

Model class : City


public class City {

	private String name;
	private String zip;

	public City(String namme, String zzip) {
		super();
		this.setName(namme);
		this.setZip(zzip);
	}

	/**
	 * @return the name
	 */
	public String getName() {
		return name;
	}

	/**
	 * @return the zip
	 */
	public String getZip() {
		return zip;
	}

	/**
	 * @param name
	 *            the name to set
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * @param zip
	 *            the zip to set
	 */
	public void setZip(String zip) {
		this.zip = zip;
	}

}

Adjustements : ILabelProvider


import com.vaadin.terminal.Resource;

public interface ILabelProvider<T> {

	String getCaption(T model);

	Resource getIcon(T model);

}

IListModelProvider


/**
 * Example for use : display a table of user's Vaadin contacts<br/>
 * U == VaadinUser.class<br/>
 * T == User.class <br/>
 * 
 * And the class VaadinUser should contains an instance variable of type List of
 * Users
 * */
public interface IListModelProvider<T, U> {

	public List<T> getModel(U baseModel);

}

the rewritten class : TwinColSelect (copy of code and adaptation)


import java.util.List;

import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
import com.vaadin.ui.AbstractSelect;

public class NewTwinColSelect<T, U> extends AbstractSelect {

	private int columns = 0;
	private int rows = 0;

	// Added
	private ILabelProvider<T> labelProvider;
	private IListModelProvider<T, U> listModelProvider;

	// End Added

	/**
     * 
     */
	public NewTwinColSelect() {
		super();
		setMultiSelect(true);
	}

	/**
	 * @param caption
	 */
	public NewTwinColSelect(String caption) {
		super(caption);
		setMultiSelect(true);
	}

	// /**
	// * @param caption
	// * @param dataSource
	// */
	// public MyTwinColSelect2(String caption, Container dataSource) {
	// super(caption, dataSource);
	// setMultiSelect(true);
	// }
	
	// Added
	public void setLabelProvider(ILabelProvider<T> labelProvider) {
		this.labelProvider = labelProvider;
	}

	public void setModelProvider(IListModelProvider<T, U> modelProvider) {
		this.listModelProvider = modelProvider;
	}

	public void setModel(U baseModel) {
		getContainerDataSource().removeAllItems();
		List<T> list = listModelProvider.getModel(baseModel);
		for (T t : list) {
			getContainerDataSource().addItem(t);
		}
	}
	// End Added
	
	/**
	 * Sets the number of columns in the editor. If the number of columns is set
	 * 0, the actual number of displayed columns is determined implicitly by the
	 * adapter.
	 * 
	 * @param columns
	 *            the number of columns to set.
	 */
	public void setColumns(int columns) {
		if (columns < 0) {
			columns = 0;
		}
		if (this.columns != columns) {
			this.columns = columns;
			requestRepaint();
		}
	}

	public int getColumns() {
		return columns;
	}

	public int getRows() {
		return rows;
	}

	/**
	 * Sets the number of rows in the editor. If the number of rows is set 0,
	 * the actual number of displayed rows is determined implicitly by the
	 * adapter.
	 * 
	 * @param rows
	 *            the number of rows to set.
	 */
	public void setRows(int rows) {
		if (rows < 0) {
			rows = 0;
		}
		if (this.rows != rows) {
			this.rows = rows;
			requestRepaint();
		}
	}

	// /**
	// * @param caption
	// * @param options
	// */
	// public MyTwinColSelect2(String caption, Collection options) {
	// super(caption, options);
	// setMultiSelect(true);
	// }

	@Override
	public void paintContent(PaintTarget target) throws PaintException {
		target.addAttribute("type", "twincol");
		// Adds the number of columns
		if (columns != 0) {
			target.addAttribute("cols", columns);
		}
		// Adds the number of rows
		if (rows != 0) {
			target.addAttribute("rows", rows);
		}
		super.paintContent(target);
	}

	// Rewriten
	@Override
	public String getItemCaption(Object item) {
// IN MY OPINION THE PROBLEM IS HERE
		return labelProvider.getCaption((T) item);
	}
	// End Rewriten
}

And finally, the example : (works now with a list of City and not a list of String)


import java.util.Arrays;
import java.util.List;
import java.util.Set;

import ch.scheuchzer.common.ui.vaadin.ILabelProvider;
import ch.scheuchzer.common.ui.vaadin.IListModelProvider;
import ch.scheuchzer.common.ui.vaadin.NewTwinColSelect;

import com.vaadin.data.Property;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.terminal.Resource;
import com.vaadin.ui.VerticalLayout;

@SuppressWarnings("serial")
public class TwinColumnSelectExample extends VerticalLayout implements
		Property.ValueChangeListener {

	private static final City[] cities = new City[]
 {
			new City("Berlin", "00100"), new City("Brussels", "00200"),
			new City("Helsinki", "00300"), new City("Madrid", "00400"),
			new City("Oslo", "00500"), new City("Paris", "00600"),
			new City("Stockholm", "00700") };

	public TwinColumnSelectExample() {
		setSpacing(true);

		NewTwinColSelect<City, List<City>> l;

		l = new NewTwinColSelect<City, List<City>>("cities : ");
		ILabelProvider<City> labelProvider = new ILabelProvider<City>() {

			public String getCaption(City model) {
				return model.getName();
			}

			public Resource getIcon(City model) {
				return null;
			}
		};
		IListModelProvider<City, List<City>> modelProvider = new IListModelProvider<City, List<City>>() {

			public List<City> getModel(List<City> baseModel) {
				return baseModel;
			}
		};
		l.setLabelProvider(labelProvider);
		l.setModelProvider(modelProvider);
		l.setModel(Arrays.asList(cities));

		l.setRows(7);
		l.setNullSelectionAllowed(true);
		l.setMultiSelect(true);
		l.setImmediate(true);
		l.addListener(this);

		addComponent(l);

	}

	/*
	 * Shows a notification when a selection is made.
	 */
	public void valueChange(ValueChangeEvent event) {
		if (!event.getProperty().toString().equals("[]")) {
			Set<City> selected = (Set<City>) event.getProperty().getValue();
			StringBuffer toShow = new StringBuffer();
			for (City city : selected) {
				toShow.append(city.getZip());
				toShow.append(", ");
			}
			if (selected.size() > 0)
				toShow.setLength(toShow.length() - ", ".length());
			getWindow().showNotification(
					"Selected cities: " + toShow.toString());
		}
	}
}

For me the problem is the AbstractSelect#getItemCaption method and its consquences. Any opinion?

Regards,

Maxime

In Vaadin, all you are really doing is manipulating bunch of components on server side. Each of these components has it’s own controller logic that is part of it. Why not just follow the same pattern as the core Vaadin framework? As Joonas (and many others) suggested, just extend CustomComponent and create your own “view”. You should split your “view” to multiple parts if it becomes big.
Vaadin is not page oriented framework, it’s component based. The layout of the page/view is dynamic and its changing based on user action. So, there is no static layout. Your component is manipulating that layout. Initial layout might be totally different when you display to user.
Business logic should be totally outside Vaadin component and that’s where Spring comes in. But, MVC just makes not much sense for me either. Especially for large projects where you need independent modules working separately/independently…

MVC is so 70s. Dump those bell bottoms and join the 90s get your hammer pants ready.

Good intro to MVP which is completely applicable to Vaadin:

http://msdn.microsoft.com/en-us/magazine/cc188690.aspx
https://developers.google.com/web-toolkit/articles/mvp-architecture
https://developers.google.com/web-toolkit/articles/mvp-architecture-2

The other major pieces missing from Vaadin in my opinion is a navigation framework (new in 7) and an event bus used to decouple high level events (e.g. contact saved).

For EventBus, use Spring or Weld or go for the Blackboard add-on… De-coupling UI modules / components from each other is beautiful concept.