LazyQueryContainer

First, thanks for a great add-on.

I had a question regarding Query#loadItems(int, int).

My query wraps a method that returns the results of a JPA query. The results of the JPA query are Object.

Now, the QueryDefinition knows what properties exist, and what the types are for each member of the array. But my query implementation doesn’t, since it is designed rather generically.

I would like to have a query be able to get to its query definition. Obviously I can do this in my own implementation, but don’t you think that a getQueryDefinition() method belongs in the Query interface?

That would allow a generic query implementation to consult its definition while it builds a List.

Thanks again,
Laird

I have made an own Query Implementation which holds a reference to the QueryDefinition.

You have to implement a QueryFactory anyway, and the QueryFactory gets the QueryDefinition injected, so you can build Queries with references to the QueryDefinition. That is no Problem.

Greetings
Volker

Hi

There is now Lazy Query Container page in Vaadin Wiki so we can collect good answers and tips to this page:


Lazy Query Container Wiki Page >>

-Tommi

I was looking through the LQC and noticed that the container implementation throws an UnsupportedOperationException for addItem(), but the LazyQueryView seems to have support for that feature? Is there a specific reason for this or have you simply forgot to publish it in the container itself? :slight_smile:

Hello,
for addItem() it does not throw an UnsupportedOperationException. See:
LazyQueryContainer.java

for the rest off the addItem(…) Method it does. That is because it is tricky, to implement a solution where Items are not added at the begining of the container.

regards,
Volker

Hi,

I have noticed a possibly bug while deleting entries through container :

Deleted entries remain selected (meaning are still present in the table.getValue() collection) in the container after commit.

Bye

DefaultQueryDefinition class is not serializable, which causes errors while restoring sessions.

All classes should be serializable now. Thanks for the heads up.

-Tommi

Hi; version 1.2.2 of LazyQueryContainer (and possibly earlier) throws an UnsupportedOperationException from the getItemIds() method. The documentation provides no indication that such an exception will be thrown. Is this a mistake, or is this by design?

Thanks,
Laird

This looks like a bug; I’ve filed https://github.com/tlaukkan/vaadin-lazyquerycontainer/issues/issue/7.

Best,
Laird

Starting to looking LQC… it looks nice.

Maybe I’m missing something obvious, but are the API JavaDocs for LQC published somewhere?

Or do I just have to generate them myself?

Thanks,
-Archie

Another question. I may be misunderstanding something, but the code in EntityQuery.saveItems() looks wrong:

        for (Item item : addedItems) {
            entityManager.[b]
persist
[/b](fromItem(item));
        }
        for (Item item : modifiedItems) {
            entityManager.[b]
persist
[/b](fromItem(item));
        }
        for (Item item : removedItems) {
            entityManager.[b]
remove
[/b](fromItem(item));
        }

Shouldn’t it be this instead?

        for (Item item : addedItems) {
            entityManager.[b]
persist
[/b](fromItem(item));
        }
        for (Item item : modifiedItems) {
            entityManager.[b]
merge
[/b](fromItem(item));
        }
        for (Item item : removedItems) {
            entityManager.[b]
remove
[/b](fromItem(item));
        }

Also, I don’t understand why it works as it is currently written. As I understand JPA, when you invoke persist() on a non-transient (e.g., detached) instance, you should get an exception.

Of course, merge() may return a different object, which should be used to replace the original, so we might need to do something like this…

        for (Item item : modifiedItems) {
            Object obj = entityManager.[b]
merge
[/b](fromItem(item));
            CompositeItem citem = (CompositeItem)item;
            citem.removeItem("bean");
            citem.addItem("bean", new BeanItem<Object>(obj));
        }

Thanks for any clarification.

AbstractBeanQuery should have a no-argument constructor to make the add-on serializable…

That’s a very interesting component.

I did try to do something similar, but did not got past the issue that
the table usually wishes to retrieve the list of ItemId’s.
And to get them, we have to (at least) load all primary keys from the database for them.

Looking at the sources I think the basic concept works that way:

  • You get the size() of the whole container, so you know how many rows exist
  • From that you make the NaturalNumbersList with a “array” of numbers from 0…size
  • The index from the NaturalNumbersList is then used as the ItemId when working with the normal Container methods
  • When retrieving objetcs for the container you then match the indexes from the NaturalNumbersList against the “real” object, or retrieve them as needed.

Very clever concept

:smiley:

Hi Tommy !

Thanks for correction the serialization issues.

I have a question : what about error handling ?

What if the AbstractBeanQuery methods (size, loadBeans etc…) have to handle exceptions or errors ? how can I display them to the user ? Do we have any reference to a Window or Application object in the add-on context ?

What would you recommend to do this ? Put a Window reference into queryConfiguration and use it ?

Thanks

Congratulations by this great Add-on!

Only one question. How can I create dynamic filters using Standard JPQL Strings? Will be possible to use JPA 2.0 Criteria API? Exist some intention to suport it?

Many thanks!

I created a JPA 2.0 extension to LazyQueryContainer that supports JPA 2.0 Criteria queries, exactly for the purpose of creating whatever dynamic filter I needed. See
JPA Criteria Lazy Container

Hello,

I’m testing LazyQueryContainer with JPA. I don’t use EntityContainer because I have 3-levels nested properties (A.B.C), so I’ve implemented Query and QueryDefinition, and items are CompositeItem.

The problem i’m facing is that my records count changes very often (it’s a database storing logs coming from different applications). As size() method seems to be called everytime I scroll down in the table, that leads to display issues in my table.

Is there any way to handle that ?

Thx,

B.R
Jerome M.

Hi,

I am trying to get this component to work and i get a strange NSME :


java.lang.NoSuchMethodException: my.app.vaadin.MyVaadinApp$MyTable$MyQuery.<init>(org.vaadin.addons.lazyquerycontainer.QueryDefinition, java.util.Map, [Ljava.lang.Object;, [Z)

This seems to indicate that my query class extending AbstractBeanQuery has the wrong constructor, however it does have the required constructor with defined arguments


            public MyQuery(QueryDefinition definition, Map<String, Object> configuration,
                    Object[] sortPropertyIds, boolean[]
 sortStates) {

Is it perhaps because the query object is a nested class within a nested class ? Or because i’m initializing the LazyQueryContainer inside a Table constructor ?

Thanks !
Jorg

PS using version 1.2.8

Terve Tommi!

I just wanted to bring one little remark out in the air. I got a bug report regarding my PagedTable that I hadn’t heard of earlier. If the amount of rows in the table is smaller than the amount of rows that can be painted on one page, the PagedTable (PT) throws a NPE. Investigating further on, I noticed that it uses the LazyQueryContainer (LQC).

I have used a trick in PT where there are two containers in the table. One is the actual container and one is just a “copy” of that container with only a pagefull of items - the ones that are visible at that moment. I check if we get into the end of the container by doing this:

for (int i = 1; i < getPageLength(); i++) {
  itemId = realContainer.nextItemId(itemId);
  if (itemId == null) {
    break;
  }
  addShownItem(itemId);
}

for some reason I got item id’s for items that did not exist and it got into addShownItem when it shouldn’t have. Reading through the source code of LQC i found this piece of code

  public final Object nextItemId(final Object itemId) {
  return (Integer) itemId + 1;
}

So the container always returns a next item id even where there is none. I fixed this by adding an additional check before addShownItem(itemId) where I fetch the actual item to see if it is null.

I just wanted to point it out because some other components might have similar issues.