Vaadin lets you build secure, UX-first PWAs entirely in Java.
Free ebook & tutorial.
Incongruence in removeItemProperty() in RowItem (UnsupportedOperationExcept
I'm trying to insert a new row into a database. The new data comes from a form, and is bind to a new temporary RowItem that is filled by the user. Not all the rows have to be inserted in the database as some are null and some other are autogenerated, although some can be manually overriden/inserted in concrete situations. For this reason I'm getting all the database row when I query them from the database, and they all "are" in my RowItem object.
So when I'm passing it to my StatementDelegate in order to be used to construct the final query (via utilities like generateInsertQuery()), I found there was a removeItemProperty() which seemed useful to me for removing "columns" (item properties) that I didn't want in the final constructed query. I was getting some exceptions, so I did a debugging session and amazingly discovered that the RowItem removeItemProperty(Object id) method, an implementation of the Item interface, was simply throwing an UnsupportedOperationException()! More surprisingly, in the Javadoc for that method it says that "Removing properties is not supported. Properties are generated by SQLContainer.".
Well, it may be that I'm not approaching it from the proper view, but I already explained a situation where I'm using a bunch of properties in my SQLContainer, coming from a RowItem, where I want to remove some of them at a certain moment. Anyway, if Vaadin designers think that properties don't have to be ever removed from a RowItem, then what's the point of implementing a method that all what it does is throwing an exception?? It's misleading and surely is not good practice, but, morevoer, one goes to the Item interface to read the specification and discovers that addItemProperty() and removeItemProperty() are "optional". "This functionality is optional.", says there. Then, why you define them in an interface? If the whole purpose of an interface is to define method functionality that **has** to be implemented in an implementing class, why do you say there that "is optional"? And why in the hell you "implement" it as a "just exception-throwing" method? Better remove it from the interface (it's your own interface! You can do it!), or don't say that class is implementing it because it's not true.
Again, I'd be happy to get some advise if my approach is terribly wrong, but finding those things that, to me, break the fundamental principles of object-oriented programming, is very discouraging.
Just for the record: if someone comes here searching about how to persist records into a database without having to send values for all columns, I accomplished it by setting the affected ItemRows to readonly (rowItem.getItemProperty("column_name").setReadOnly(true)) in my StatementDelegate. Appart from this, my previous message/question/doubt still applies.
I know SQLContainer it's been deprecated, but I still don't understand it's sole purpose. I still haven't switched to v8 and keep stepping with the same stone one time after other.
This is my current case:
- I have a Grid where I display a set of data, coming from a database query. So it's bind to an SQLContainer.
- I also hava a form for simple CRUD, which allows me to insert new records (rows on the grid, in the end).
- I have generic filters for each column, usually in the shape of a TextField.
- I discovered (time ago) that neither filtering nor columns sorting (by clicking on its header) work if I don't set a StatementDelegate for my FreeFormQuery when I initialize my SQLContainer. So I created a "dummy" one, which does almost nothing. But, again, it's needed if I want to perform those sorting/filtering operations.
By the way. I traced down that Delegate requirement to somewhere in the code where, if there is no delegate, it will SILENTLY FAIL. Yeah, it simply won't work without further notice.
Can anyone tell me who designed that? There are a couple of exceptions that are simple captured, logged and silently ignored. How are we supposed to notice something is failing, appart from long hours of debugging, tracing and pulling hour hair?
Well, let's continue...
- As I may need them later, I have grown used to put the Primary Keys of my tables in each Delegate. Also they are used for some operations by the framework, and also I suspiced its presence had something to do on making Grid filtering work by means of being present in the Delegate.
- But suddenly my form for creating new records and storing new items on the database stopped working. After another big amount of many hours of debugging, I traced it down to the place where I was adding a new Item to the dataSource. I did it as simply as this way:
newItemId = dataSource.addItem();
But them, when retrieving the new item,
Item newItem = dataSource.getItem(newItemId);
(which I later filled with the proper values and stored into the database), I suddenly found that it was NULL.
Why, if it previously worked??
I won't go much deeper into the further details that made me spend DAYS for tracing it down to itemPassesFilters(item) in SQLContainer.java, circa 582. It would make the new item not being found across the list of new items. Only because my Primary Key consist of TWO columns, both of them being NULL at the moment the new item is created. And I happened to have an EQUALS filter on the DataSource which affects to one of these two columns, making it fail as a NULL value will never be equal to the value of my filter.
So while looking for a solution, I tried several attempts, which didn't work, like:
- Modifying the value of the temporary row id, trying to manually set the same value for the affected column as the one in the filter. Which obsviously didn't work as I cannot directly manipulate the object.
- Then I tried to manually generate my new item id with the proper value for the pk column, as I found that and
existed in SQLContainer...
...just to find that it belongs to a big bunch of
/************************************/ /** UNSUPPORTED CONTAINER FEATURES **/ /************************************/
(as stated in the source code), adding another big bunch of frustration and lost time and effort. Why do those method exist on there and why are they not implemented??
In the end, THE ONLY THING THAT WORKED WAS **REMOVING THE PRIMARY KEY DEFINITION** FROM MY StatementDelegate. That way, the comparison works, as the new item "doesn't have" a PK and its check agains itemPassesFilters never fails. My Delegate is pretty empty now. Then, why do I need it to get filtering working?!?!?
Why the hell this crazy big amount of nonsenseless, non-understandable architecture, silently-failing operations, nonsensical checks, non-implemented methods, undocumented undecipherable operations, absurd and over-complicated logic, unneeded compulsory requirements which does nothing (like Delegates) and, in the end, this incredible amount of clumsiness? If I could understand it...
You cannot guess the amount of time, effort and desperation I've spent on those crazy issues in Vaadin.