Important! can vaadin team rethinking data-binding?

Hi,Vaadin team,I think vaadin is a very powerful tools to construct UI,but I find It’s difficult to build a real enterprise business application using vaadin now,from my view,primarily because of vaadin’s data binding mechanism.
For example,I need to build employee-manager application,I need a search-list-table as main page. and when user click item in employee table,switch to edit-form page,when user edit and save the emplyee,return to search-list-table main page,the business is very basic and simple.
If I use vaadin-fashion to build this application,the main work I need to do: build the employee-table and set containerDatasource,and the edit-form then set itemDatasource…
I am forced to implement the business logic in Container-Item fashion,It’s very mysterious,complex and ugly… I began to shake with fear because I am not sure when and how many times each container’s method will be executed. for example:container has a method getItemIds(),it will return all record id,in huge data scene,this will be horrible performce killer.
And more fatal issue:when to refresh all employee-table’s data? I can understand vaadin’s logic,it’s more like C/S fashion,but we live in web. when user press F5 ,it means he want to get lastest data.

and the following is my imagined solution:

  1. Component interface need a bind method,in this method,data (re)populate logic will be implemented,application developer can use his favorite technique to get data ,like Spring-JDBC,hibernate,cache… etc,not limited to implement container-related interface.then use addItem(for example Table) to populate the table.
  2. ComponentContainer’s bind invoke children component’s bind.
  3. After Component created,and before paint,the bind method is invoked by vaadin framework.
  4. Applicaton developer can invoke bind to repopluate component’s data in event listener.
  5. bind method invoking order is no guarantee,so developer need to process bind dependence relation by himself.
  6. when F5 pressed,all component’s bind will be invoked by vaadin framework.

Best rgds

L.J.W

"
I am forced to implement the business logic in Container-Item fashion,It’s very mysterious,complex and ugly
"
Not at all. I fear the issue is indeed the fact you don’t understand how Container works rather than in the design of the data binding. I don’t say the latter cannot be improved, but it works.

I just made a prototype with Vaadin. I implemented the business logic (data model) in packages totally oblivious of the application using it. I can easily go back to Swing, or use JavaFX to exploit this data, if I want.
I made two classes to handle the data model on the Vaadin application side: a ReportContainer, to hold a Table’s data, implementing just AbstractContainer (I could have used AbstractInMemoryContainer but I prefer to do myself the stuff it does, as filtering, for example, is handled on the business logic side) and Container.Ordered (because otherwise Table with wrap the container to have Ordered data). On second though, I don’t use Filterable or Sortable, again, doing that on the other side.

I implemented just the some 13 required methods (plus some UnsupportedOperationException because my data is read-only). You have to add 8 more if you modify the data. That’s for the “complex” side.
I also have a ReportRow implementing Item, 2 methods and 2 unsupported ones.
Again, no business logic here, only accessing the face of the API of my BL designed to expose data.

Mysterious? A bit, I admit. I had to implement a number of methods with little idea of how they are used… Stuff like getItemProperty / getItemPropertyIds for Item (the latter is never called in my app.), containsId, getContainerPropertyIds or getContainerProperty for Container.
I made mock-up methods, added System.out.println() to see what parameters we get and when they are called, then I had a better understanding of the Table mechanism.

Moreover, looking at existing Container implementations, both in the Vaadin sources and from the Add-on Directory, helps a lot in understanding how this works.
The documentation can be improved (eg. in Table.setPageLength(), what is a page length? What is the unit (I found it is expressed in rows, but it is better to say it so)), but it is rather good, overall.
I found out the data binding logic to be quite easy to get and to use. Now, I am a Swing programmer, and this logic isn’t far from Swing’s logic, so perhaps it helped.

"
I am not sure when and how many times each container’s method will be executed
"
The println (or any log system you can have) method is useful to have real data on this kind of question…

"
for example:container has a method getItemIds(),it will return all record id,in huge data scene,this will be horrible performce killer.
"
I made a report with some 10,000 rows. No performance problem here. That’s a list of 10,000 ids (small objects) to return, it isn’t that big in an industrial Java application. Even a million of rows is still not a problem. One trick is to build the list once, and cache it. So on the next calls, you just serve this list, if it hadn’t changed.
Don’t fear performance issues, measure them! See where is the bottleneck (if you have any) with a profiler (like JVisualVM) and address the specific, real issue, not your fears.

"
we live in web. when user press F5 ,it means he want to get lastest data.
"
I don’t know if F5 works well in a Vaadin application (can be problematic if you still have ?restartApplication in the URL…) but nothing prevents you to bind another key to mean “refresh displayed data”, and to update the container or just call fireItemSetChange() to update the view.

"
(re)populate logic will be implemented,application developer can use his favorite technique to get data ,like Spring-JDBC,hibernate,cache… etc,not limited to implement container-related interface
"
To my knowledge, this kind of container already exists…

Maybe I don’t fully understand your proposal, but it looks like what you request can be already done with the existing code.
Maybe your message is a sign we need a step-by-step tutorial on how to build a custom container (another one, with a different angle, if
it already exists
).

I never got around to making a tutorial out of this, but attaching a short example of how to write your custom AbstractInMemoryContainer. It shows alerts from the Finnish rescue services on a map and allows filtering by drawing a polygon etc. The example is quite old so the versions used in it etc. should be updated - I originally did this as a demo where I wrote the container in 20 minutes as a part of a presentation.

The minimal AbstractInMemoryContainer implementation would only need to implement one method (getUnfilteredItem(id)) and populate the item IDs for the container somehow. Filtering, sorting etc. often require a few public methods that delegate functionality to the superclass and minimal specific code.
12031.jar (12.1 KB)

As for the plans for Vaadin 7 regarding data binding and other features, see the blog post and wiki page links in
this post
as well as the discussion in that thread.

I think I must read the vaadin code,to understand how container working,this is a hard work to newbie…

I don’t think so,retrieve 10000 rows once from db is a horrible things,you can have a stress testing to view the result.

My meaning is data changed by other online user concurrently.or other,data in database is changed from outside,when press F5,vaadin not get the lastest data.you can refer
https://vaadin.com/forum/-/message_boards/view_message/45510,I can not find official solution to this issue.

Hi,

Item ID’s do not have to be the database primary key, therefore you do not need to touch the database to implement getItemIds. For example, we use the row number as the ItemID. If you know how many rows there are (and you need to, for container to work) it is a) trivial and b) relatively inexpensive to create a collection of10,000 integers. Sure, it could be a bit cleaner - but it is totally possible to deal with many thousands of rows in a database in a container, and to display those in a table (without loading all of the dataset); I know this, because we are doing it!

Cheers,

Charles.

If ItemId can express with integer(row number),then there are no necessary getItemIds .but It seems it’s better express ItemId as Record Key. and even if ItemId can express with row number,how to process data in database changed outside(record count changed)?
I try to read sourcecode to understand table’s work mechanism.and I find this is a hard work to many people(table.java has 4900 rows).I can not find a solution to let table retrieve lastest data in database when user press F5.

(Can I overide table paintcontent method like following?

public void paintContent(PaintTarget target) throws PaintException {
super.refreshRenderedCells();//before paint,refersh pageBuffer.
super.paintContent(target);
}
)

I think these issue I mention is about vaadin’s architecture.Maybe, it’s better vaadin devote it’s mind to UI, not care for how data retrieve from and commit to database,like swing and other UI framework. we can retrieve data using our favorite and then populate to vaadin’s UI component.

I need to say vaadin’s data binding is complex indeed(I can see many many people mention this),It’s a truth.

Hi,

It is totally possible to create a container that load many thousands of rows from a database, page them, and display them. I am not an alpha geek - hell, I’m not even a gamma geek - just a plain 'ole normal trudging enterprise coder, yet I’d built a paging container, from scratch, within a fortnight of starting to use Vaadin.

FWIW, Vaadin doesn’t care about retrieving and committing data to the database (outside of the SQL and JPA containers). It does, however, give you a series of interfaces to implement, and some default implementations. Yes, it’s containers and items are complex, verbose and frequently opaque. Yes, it needs some attention - no argument from me here.

It works, though, and with a little study can do most things now : any refactoring of the Item/Container framework would have severe backwards compatibility issues, and hence is being addressed in Vaadin 7 - which is unlikely to be fully released until September 2012; for more details on the plans, see the
Vaadin 7 page on the Wiki

Concrete Things, for Vaadin As It Stands Now:

Using the row number is the best way to cope with large numbers of rows in a container. When the number of rows changes, you can fire an Container.ItemSetChangeEvent event, and the table will refresh it’s entire buffer (and number of rows)

You can’t trap and use F5 (or the refresh button) in Vaadin : it just isn’t going to work. Vaadin is an AJAX frameowrk - you typically have one page , and the contents change. It may appear like many pages, but in reality it usually only one. F5/Refresh says “reload the whole page”, which is pretty much contrary to the whole point of AJAX! Vaadin “just” re-renders the UI. The simplest approach for providing the user an facitily to refresh the data would be to include a button in your app that refreshes your container. If you wanted to be more complex and sophisticated, you could have use the Refresher or one of the Server Push add-ons to update container when the number of rows/data changes (assuming you know this)

You could refresh the buffer where you indicate (in paintContent) but i would suspect that will result in performance issues. (paintContent is called when the table scrolls)

I don’t wish to appear overly negative - there are issues and complexities with Vaadin containers; I think, though, the concerns you are raising (about using the F5/refresh cycle of the browser) might suggest that Vaadin is not the framework for you.

With Sincere Best Wishes,

Charles.

Hi,
Firstly,Thanks for you quick response.
I think my terrified feeling to vaadin-databing originate from the performance issue,I add System.out.println to Container API,and find a great many of method calling to Container API when a table show.It’s not hard to implement Container API function,difficulty is the the implementation must be high performance.there are many trip.
And wish vaadin’s data binding API (include data-binding Component like Table) will be more clear and high performance.

Don’t give me up easily:-) I am a vaadin faithful fans.

I can understand you meaning fully,but If vaadin can offer some mechanism to give developer a chance to refresh data when user press F5.that’s will be more exciting.
and my advice has mentioned in my question,copy and describe again:

  1. Component interface need a bind method,in this method,data (re)populate logic will be implemented,application developer can use his favorite technique to get data ,like Spring-JDBC,hibernate,cache… etc,not limited to implement container-related interface.then use addItem(for example Table) to populate the table.
  2. ComponentContainer’s bind invoke children component’s bind.
  3. After Component created,and before paint,the bind method is invoked by vaadin framework.
  4. Applicaton developer can invoke bind to repopluate component’s data in event listener.
  5. bind method invoking order is no guarantee,so developer need to process bind dependence relation by himself.
  6. when F5 pressed,all component’s bind will be invoked by vaadin framework.

sketch code:
1.Component interface add public void bind(); method. AbstractComponent implement this method,default do nothing.

    public void bind() {
        if (!THREAD_SCOPE.get().containsKey(this)) {
            THREAD_SCOPE.get().put(this, Boolean.TRUE);
            bindInternal();
        }
    }

    protected void bindInternal() {
        //default do nothing
    }

2.AbstractComponentContainer implement bind method,to invoking recursive-children’s bind :

    protected void bindInternal()  {
        final Iterator<Component> it = getComponentIterator();
        final CopyOnWriteArrayList<Component> childes = new CopyOnWriteArrayList<Component>();
        while (it.hasNext()) {
            childes.add(it.next());
        }
        for (Component child : childes) {
            if (child.getParent() != null)
                child.bind();
        }
    }

3.Developer can override bind() in his Component,example in PersonTable(extends Table) :

protected void bindInternal()  {
    //get biz data using his favorite fashion.
    List<Person> persons = bizService.getPersons(...);
    //firstly,clean current table data,and then populate table using persons.need protect status like current selection.
    getContainerDataSource().removeAllItems();
    for (Preson person : persons) {
              addItem(person.getData(),person.getId());            
     }        
}

4.vaadin framework invoke Root ComponnetContainer after Application’s init() method.
5.vaadin framework intercept F5 request,do a full rebind,I am using TransactionListener:

    public void transactionStart(Application application, Object transactionData) {
        if (transactionData instanceof HttpServletRequest) {
            HttpServletRequest request = (HttpServletRequest) transactionData;
            //if current is browser-refreshing
            if (request.getParameter("repaintAll") != null) {
                getContent().bind();
                for (Window subWindow : getChildWindows()) {
                    if (subWindow.isVisible())
                        subWindow.bind();
                }
            }
        }
    }

I try to express another vaadin usage fashion to solve question I mentioned.Wish vaadin team can conside my suggestion.

Best Rgds

L.J.W

I find this response EXTREMELY disappointing. Perhaps you haven’t considered the way many people use web browsers today. They leave many tabs open, and refresh them to see the updated information. (and how many do you have open as you read this??) You also appear to be proscribing to users how they should use their browser. This is the sort of thing I would expect from M$ not Vaadin. It is also the sort of things sooo many applications and frameworks have previously said about the back button… and annoyed users to the point where support for the back button is now a headline feature for Vaadin. [1]

If the back button is important why on earth isn’t the refresh button important?? Really folks, DON’T break the browser :).

Vaadin should detect a refresh, and fire an RefreshEvent, and allow components to register to listen for refresh events.

[1]

https://vaadin.com/features

Disapointed as you may be, browsers simply do not have a “Refresh” event. Sorry. None.

They only have a “I’m leaving” event, and a “I’m arriving event”. If the browsers (and its native JavaScript support) do not tell Vaadin (or anyone for that matter) that a refresh occurred, there is no miracle to be had. And the “I’m leaving event” is actually the same for “I’ve closed the Tab”, “I’ve closed the browser”, and “I’ve clicked on a link” and “I’ve hit F5, control-R, or the Refresh menu”, or “I’ve used the back button”.

On the topic of the back button, JavaScript, GWT, and thus Vaadin don’t get told “back”. They get told “I’m leaving”, and the place you land next is wherever the browser brings you. By sheer astuteness, it happens that if the previous URL had a URL fragment in it, the browser can remember what page that was and do something sensible with it. You can look up AJAX history management for details.

In short, you’re asking for something that is, in the general case, not doable, and in the cases where something can be done to approximate it, very difficult and brittle.

This would be an issue if the problem were a browser level problem (i.e. we wanted to write generalized javascript to recognize any refresh event in any web page). However, I’m not asking for a solution that works in any web page. Also, I don’t see a reason to care what the cause of the request is (be it refresh button, F5 key, Opening the same page in a second tab when we don’t have a clue that one of the 49 tabs open is already displaying the vaadin ap… etc.)

In fact all we want to do is give the user fresh data when they initiate a novel request for the page. In other words we need only detect a request to the SERVER that didn’t come from a vaadin UI widget, and fire an event if we detect such a request.

I can think of several approaches to do that.

To Henri Sara,

Thank you
so much
for sharing that “alertmap_src.jar” source-code example of subclassing
AbstractInMemoryContainer
.

I seem to have my own subclass now up and running. I truly could not have done it without you.

And thanks to the Vaadin team for their foresight and refactoring work in recently providing this useful abstract class.

I entered
Ticket # 8881
asking for a simple example implementation to be added to the Vaadin doc.

I agree, I keep getting end-users complaining about F5 not refreshing the data on the page. Wish there was a way to capture that event. Oh well.

Hi,

In Vaadin 7, you could just have relevant components (layouts/views/your UI/whatever) override the beforeClientResponse -method. It has a boolean parameter “initial” which will be true when the client-side connector will be created after this call - essentially the component is shown for the first time.

If you override this method in UI, you will get a call with initial=true whenever the page is rendered from scratch. From there you can use any event mechanism to trigger any data refreshing you need.