Java EE7アプリケーションでJava.util.List<T>
の並べ替えやフィルタリングなどのタスクにGoogleGuavaライブラリを使用しています。
以下に、CDIBeanのフィルターのリストに基づいてJava.util.List<T>
をフィルター処理する例を示します。
@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;
}
}
}
ネストされたクラスは、次のようにCDIBean内からJava.util.List<T>
をフィルタリングするために使用できます。
List<T> list = //Initialize the list here to be filtered.
//...
list = FluentIterable.from(list).filter((new Filtering(filters))).toList();
ここで、filters
はフィルターのリストを保持するJava.util.Map<String, Object>
です。
これは、以前はJava EEアプリケーションとJSF Managed Beans(GlassFish 4.0)で正常に機能していました。
このアプリケーションをCDI Managed BeansでGlassFish 4.1に移行したところ、次の例外が発生しました。
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)
両方のアプリケーションでGuava17.0を使用しています(再確認しました)。
グアバがCDI豆を嫌うのはなぜですか。解決策/回避策は何でしょうか?
更新:
バージョンを18.0に変更しようとしましたが、新しいことは何も起こりませんでした。
クラスパスに複数のバージョンのGuavaがあります。 GuavaクラスのNoSuchMethodError
はここに来ますSOおそらく週に1回です。古いバージョンを削除しない限り、新しいバージョンに切り替えても役に立ちません。 FluentIterable.class
の場所を印刷して、そのJARを削除します。
Frank Pavageauがコメントしたように、この場所は次のように取得できます。
FluentIterable.class.getProtectionDomain().getCodeSource().getLocation().toExternalForm()
これはGlassFishの既知の問題です。 GlassFish 4.1で他の変更がない場合、Guava 13.0.1が使用されるため、そのバージョンに存在しない機能を使用すると、前述のようなエラーが発生します。私の場合はJava.lang.IncompatibleClassChangeError: Implementing class
でした。
バグレポート のコメントでは、glassfish/modules/guava.jar
を置き換えることが提案されています。これが最も簡単な解決策のようです。別のアプローチは、カスタムクラスローダーを使用することです。
編集:<class-loader delegate="false"/>
をglassfish-web.xml
に追加すると、GuavaがWARからロードされます。
エラーJava.lang.NoSuchMethodErrorを下回っていました:com.google.common.collect.FluentIterable.append(Ljava/lang/Iterable;)Lcom/google/common/collect/FluentIterable; 16.0.1からguavaバージョン20.0に切り替えると、問題が修正されました。