Container.Filter + JPAContainer exception "Cannot find any converts for ...

Hi Folks,

I’m trying to create my first Container.Filter to filter a JPAContainer (1.2.1 and 2.0.0-nightly snapshot) but I keep getting the
exception shown below. I’ve been scratching my head pretty hard for the last day trying to figure this one out.

My Container.Filter class (LimitFilter) is at the bottom of this posting. From the output, the class is instanciated, but passesFilter() and appliesToProperty() are never called.

Anybody have any suggestions or examples of a custom Container.Filter class?

Would appreciate some pointers before all my hair is gone!

Thanks.

mike


LimitFilter: limitIds=<[1222, 1234]
>
Dec 29, 2011 1:55:33 PM com.vaadin.Application terminalError
SEVERE: Terminal error:
com.vaadin.event.ListenerMethod$MethodException
Cause: java.lang.IllegalStateException: Cannot find any converters for LimitFilter filters!
	at com.vaadin.event.ListenerMethod.receiveEvent(ListenerMethod.java:532)
	at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:164)
	at com.vaadin.ui.AbstractComponent.fireEvent(AbstractComponent.java:1219)
	at com.vaadin.ui.Button.fireClick(Button.java:550)
	at com.vaadin.ui.Button.changeVariables(Button.java:217)
	at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.changeVariables(AbstractCommunicationManager.java:1445)
	at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.handleVariableBurst(AbstractCommunicationManager.java:1393)
	at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.handleVariables(AbstractCommunicationManager.java:1312)
	at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.doHandleUidlRequest(AbstractCommunicationManager.java:763)
	at com.vaadin.terminal.gwt.server.CommunicationManager.handleUidlRequest(CommunicationManager.java:296)
	at com.vaadin.terminal.gwt.server.AbstractApplicationServlet.service(AbstractApplicationServlet.java:501)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
	at vortex.request.EntityManagerRequestFilter.doFilter(EntityManagerRequestFilter.java:72)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
	at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:405)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:279)
	at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:515)
	at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:302)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
	at java.lang.Thread.run(Thread.java:662)
Caused by: java.lang.IllegalStateException: Cannot find any converters for LimitFilter filters!
	at com.vaadin.addon.jpacontainer.filter.util.FilterConverter.convertFilter(FilterConverter.java:261)
	at com.vaadin.addon.jpacontainer.provider.LocalEntityProvider.doGetEntityCount(LocalEntityProvider.java:460)
	at com.vaadin.addon.jpacontainer.provider.LocalEntityProvider.getEntityCount(LocalEntityProvider.java:489)
	at com.vaadin.addon.jpacontainer.JPAContainer.size(JPAContainer.java:872)
	at com.vaadin.ui.AbstractSelect.size(AbstractSelect.java:721)
	at com.vaadin.ui.Table.setCurrentPageFirstItemIndex(Table.java:1262)
	at com.vaadin.ui.Table.containerItemSetChange(Table.java:3865)
	at com.vaadin.addon.jpacontainer.JPAContainer.fireContainerItemSetChange(JPAContainer.java:248)
	at com.vaadin.addon.jpacontainer.JPAContainer$1.filtersApplied(JPAContainer.java:165)
	at com.vaadin.addon.jpacontainer.filter.util.AdvancedFilterableSupport.fireListeners(AdvancedFilterableSupport.java:86)
	at com.vaadin.addon.jpacontainer.filter.util.AdvancedFilterableSupport.applyFilters(AdvancedFilterableSupport.java:209)
	at com.vaadin.addon.jpacontainer.filter.util.AdvancedFilterableSupport.addFilter(AdvancedFilterableSupport.java:243)
	at com.vaadin.addon.jpacontainer.JPAContainer.addContainerFilter(JPAContainer.java:954)
	at vortex.console.ui.component.ListTable.configureLimitFilter(ListTable.java:456)
	at vortex.console.ui.component.ListTable.configure(ListTable.java:413)
	at vortex.console.ui.component.ListTable.makeTable(ListTable.java:338)
	at vortex.console.ui.component.ListTable.getTable(ListTable.java:274)
	at vortex.console.ui.component.ListTable.getListLayout(ListTable.java:908)
	at vortex.console.ui.component.ListTable.setDefaultView(ListTable.java:838)
	at vortex.console.ui.table.GroupsTable.init(GroupsTable.java:121)
	at vortex.console.ui.table.GroupsTable.<init>(GroupsTable.java:81)
	at vortex.console.ui.slate.GroupsMetaSlate.getTable(GroupsMetaSlate.java:71)
	at vortex.console.ui.slate.GroupsMetaSlate.setDefaultView(GroupsMetaSlate.java:88)
	at vortex.console.ui.slate.GroupsMetaSlate.init(GroupsMetaSlate.java:62)
	at vortex.console.ui.slate.GroupsMetaSlate.<init>(GroupsMetaSlate.java:30)
	at vortex.console.ui.slate.PolicyMetaSlate.loadGroupSection(PolicyMetaSlate.java:399)
	at vortex.console.ui.slate.PolicyMetaSlate.getGroupSection(PolicyMetaSlate.java:389)
	at vortex.console.ui.slate.PolicyMetaSlate.makeContent(PolicyMetaSlate.java:213)
	at vortex.console.ui.slate.PolicyMetaSlate.getSection(PolicyMetaSlate.java:190)
	at vortex.console.ui.slate.PolicyMetaSlate.getTabContent(PolicyMetaSlate.java:171)
	at vortex.console.ui.PolicyTab.getContentForTab(PolicyTab.java:145)
	at vortex.console.ui.PolicyTab.getTabContent(PolicyTab.java:321)
	at vortex.console.ui.component.VerticalTabSheet.loadTab(VerticalTabSheet.java:309)
	at vortex.console.ui.component.VerticalTabSheet.loadTab(VerticalTabSheet.java:292)
	at vortex.console.ui.component.VerticalTabSheet.buttonClick(VerticalTabSheet.java:370)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at com.vaadin.event.ListenerMethod.receiveEvent(ListenerMethod.java:512)
	... 30 more

Here is LimitFilter


    private class LimitFilter implements Container.Filter {
	private Trace 			log = TraceFactory.getTrace(LimitFilter.class);
	protected Set<Object>		limitIds;

	public LimitFilter(Set<Object> limitIds) {
	    this.limitIds = limitIds;
	    System.err.printf("LimitFilter: limitIds=<%s>\n", limitIds);
	}
	
	@Override
	public boolean passesFilter(Object itemId, Item item) throws UnsupportedOperationException {
	    String		m = "passesFilter";
//	    log.debug(m, "itemId=<%s> item=<%s>", itemId, item);
	    System.err.printf("itemId=<%s> item=<%s>\n", itemId, item);
	    if (limitIds.contains(itemId))
		return false;
	    else
		return true;
	}

	@Override
	public boolean appliesToProperty(Object propertyId) {
	    String		m = "appliesToProperty";
//	    log.debug(m, "propertyId=<%s>", propertyId);
	    System.err.printf("propertyId=<%s>\n", propertyId);
	    return true;
	}
    }
    

Edit: this answer is for JPAContainer 2.0 (and its snapshots), which I strongly suggest all JPAContainers to start using.

Hi,

Container.Filter API is not a full implementation with JPAContainer. The Container.Filter expects the filter can be applied to each item in the container. But JPAContainer is bit special in this case as it does all its filtering at JPA (~ database) level. Some flexibility is lost, but lots of memory and DB queries are saved.

JPAContainer has converters for standard Vaadin filters, which modify the DB query to do the filtering on DB level with JPA Criteria API. Extending those converters is not currently possible. We might consider that later but currently we are hoping that QueryModifierDelegate (see below) will solve more complex filtering needs.

I have two possible methods to solve your issue:

  1. Build your filter with combination of And and n * Compare filters.
  2. Hook QueryModifierDelegate delegate to your entity provider and implement filtering with JPA 2.0 Criteria API

I hope this helps!

cheers,
matti

Matti,

Many thanks for setting me on the right path once again!

This code seems to work though I am worried about performance:


	JPAContainer<T> container = getAdvContainer();
	container.setApplyFiltersImmediately(false); // Wait for explicit
	container.removeAllContainerFilters();
	
	List<Filter> eqFilters = new ArrayList<Filter>();
	String key = ModelCoreProperty.ID_DBID; // database ID
	for (T entity : entities) {
	    if (entity instanceof ModelCore) {
		ModelCore mc = (ModelCore) entity;
		eqFilters.add(Filters.eq(key, mc.getDbID())); // Item's database ID
	    } else {
		log.err(m, "Entity <%s> is not ModelCore", entity.getClass().getName());
	    }
	}
	log.debug(m, "Adding %d Equal filters", eqFilters.size());
	container.addContainerFilter(Filters.or(eqFilters));
	
	container.applyFilters();

My performance concern (and the reason why I started down the path of a custom filter) was that the approach above may be too slow. The container may eventually contain thousands of items and sometimes the list of container items I wish to limit being displayed could be up to 99% of all the items in the container. I wanted to implement a filter which was as lightweight as I could given this scenario. Any thoughts on this?

I have the same concerns, did you solved with custom filter?

Why isn’t it possible to extend the
com.vaadin.addon.jpacontainer.filter.util.FilterConverter
with custom converters like it is in SQLContainer’s
com.vaadin.data.util.sqlcontainer.query.generator.filter.​QueryBuilder
where a custom implementation of
com.vaadin.data.util.sqlcontainer.query.generator.filter.FilterConverter
can be added?

Hi,

I think you should consider JPAContainer as a “deprecated” component. There are
much better ways to use JPA entities in Vaadin UI
.

cheers,
matti