12

I'm using the Google Guava library for tasks like sorting and filtering of a java.util.List<T> in a Java EE 7 application.

Given below an example of filtering a java.util.List<T> based on a list of filters in a CDI bean.

@Named
@ViewScoped
public class Bean extends LazyDataModel<T> implements Serializable {

    private static final long serialVersionUID = 1L;

    private final class Filtering implements Predicate<T> {

        private final Map<String, Object> filters;

        public Filtering(Map<String, Object> filters) {
            this.filters = filters;
        }

        @Override
        public boolean apply(T p) {
            if (p == null) {
                return false;
            }

            Integer id = (Integer) filters.get("id");

            if (id != null && !p.getId().equals(id)) {
                return false;
            }

            BigDecimal size = (BigDecimal) filters.get("size");

            if (size != null && ((p.getSize().compareTo(size) < 0))) {
                return false;
            }
            return true;
        }
    }
}

The nested class can be used to filter a java.util.List<T> from within the CDI bean as follows.

List<T> list = //Initialize the list here to be filtered.

//...

list = FluentIterable.from(list).filter((new Filtering(filters))).toList();

Where filters is a java.util.Map<String, Object> holding a list of filters.


This was working fine previously in a Java EE application with JSF Managed Beans (on GlassFish 4.0).

I migrated this application to GlassFish 4.1 with CDI Managed Beans and the following exception occurred.

SEVERE:   java.lang.NoSuchMethodError: com.google.common.collect.FluentIterable.toList()Lcom/google/common/collect/ImmutableList;
    at util.mesurements.custom.beans.BackNeckDepthManagedBean.load(BackNeckDepthManagedBean.java:184)
    at org.primefaces.component.datatable.DataTable.loadLazyData(DataTable.java:838)
    at org.primefaces.component.datatable.feature.FilterFeature.encode(FilterFeature.java:102)
    at org.primefaces.component.datatable.DataTableRenderer.encodeEnd(DataTableRenderer.java:78)
    at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:919)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1863)
    at com.sun.faces.context.PartialViewContextImpl$PhaseAwareVisitCallback.visit(PartialViewContextImpl.java:582)
    at com.sun.faces.component.visit.PartialVisitContext.invokeVisitCallback(PartialVisitContext.java:183)
    at org.primefaces.component.api.UIData.visitTree(UIData.java:692)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
    at javax.faces.component.UIForm.visitTree(UIForm.java:371)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
    at com.sun.faces.context.PartialViewContextImpl.processComponents(PartialViewContextImpl.java:403)
    at com.sun.faces.context.PartialViewContextImpl.processPartial(PartialViewContextImpl.java:322)
    at javax.faces.context.PartialViewContextWrapper.processPartial(PartialViewContextWrapper.java:219)
    at org.primefaces.context.PrimePartialViewContext.processPartial(PrimePartialViewContext.java:60)
    at javax.faces.component.UIViewRoot.encodeChildren(UIViewRoot.java:1004)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1856)
    at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:430)
    at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:133)
    at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:337)
    at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:337)
    at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:120)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:219)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:647)
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1682)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:344)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
    at org.primefaces.webapp.filter.FileUploadFilter.doFilter(FileUploadFilter.java:72)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
    at filter.NoCacheFilter.doFilter(NoCacheFilter.java:28)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:316)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:415)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:282)
    at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:459)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:167)
    at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:201)
    at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:175)
    at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:235)
    at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:284)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:201)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:133)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112)
    at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
    at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:561)
    at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:565)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:545)
    at java.lang.Thread.run(Thread.java:722)

I'm using Guava 17.0 on both the applications (double checked it).

Why does Guava dislike CDI beans. What might be the solution/workaround?


UPDATE :

I tried changing the version to 18.0 but nothing new happened.

Tiny
  • 27,221
  • 105
  • 339
  • 599
  • Are you using the library local within your WAR or is it deployed to the app server? – John Ament Oct 21 '14 at 00:25
  • The library is local to WAR. It is stored in the `/WEB-INF/Lib` directory and added to the classpath (in both the applications - one with JSF managed beans and the other with CDI beans). – Tiny Oct 21 '14 at 00:53

3 Answers3

17

You have multiple versions of Guava on your classpath. NoSuchMethodError in a Guava class comes here on SO maybe once per week. Switching to a newer version won't help as long you don't get rid of the old one. Print out the location of FluentIterable.class and get rid of that JAR.

As Frank Pavageau commented, this location can be obtained as

FluentIterable.class.getProtectionDomain().getCodeSource().getLocation().toExte‌​rnalForm()
maaartinus
  • 44,714
  • 32
  • 161
  • 320
  • 5
    To complete the answer, the location of the class is obtained with `FluentIterable.class.getProtectionDomain().getCodeSource().getLocation().toExternalForm()`. – Frank Pavageau Oct 21 '14 at 08:54
  • The duplicate JAR comes from Weld/GlassFish itself. you'll need to downgrade to 16 and mark it as provided (don't bundle it). This is however likely a regression issue w/ GF 4.1 as it seems like classloader isolation worked better in 4.0 – John Ament Oct 21 '14 at 11:53
  • Another way to see the class locations with GlassFish is to add `-verbose:class` to the server-config JVM options (can be done using the admin GUI or editing the `domain.xml`; probably there is an `asadmin` command, too) and starting the server with `asadmin start-domain --verbose`. – Martin Jun 02 '15 at 13:12
  • if you are using Gradle it's could be more useful to get dependency insights ./gradlew :app:dependencyInsight --configuration compile --dependency guava To get an idea which jar dependant from old guava – Yevgen Kulik Aug 20 '18 at 08:25
6

This is a known GlassFish issue. With GlassFish 4.1 and no other modifications, Guava 13.0.1 is used so when you use features not present in that version, you will get errors like the one you stated. In my case, it was java.lang.IncompatibleClassChangeError: Implementing class.

In the comments of the bug report it is suggested to replace glassfish/modules/guava.jar. This seems to be the easiest solution. Another approach is to use a custom class loader.

Edit: If you add <class-loader delegate="false"/> to your glassfish-web.xml, then Guava is loaded from the WAR.

Martin
  • 2,573
  • 28
  • 22
2

I was getting below error java.lang.NoSuchMethodError: com.google.common.collect.FluentIterable.append(Ljava/lang/Iterable;)Lcom/google/common/collect/FluentIterable; switching to guava version 20.0 from 16.0.1, fixed the issue for me.

Sonam Shinare
  • 231
  • 2
  • 3