我刚刚尝试使用最新版本的 Guice 和 Sitebricks (4.0-beta5) 和 (0.8.10) 将 Sitebricks 网站上的示例 HelloWorld 应用程序部署到 GAE,但注入失败。这是 Google App Engine 日志显示的内容:
Uncaught exception from servlet
com.google.inject.CreationException: Unable to create injector, see the following errors:
1) An exception was caught and reported. Message: Unable to get members for class com.google.inject.multibindings.Multibinder$RealMultibinder
at com.google.sitebricks.SitebricksModule.configure(SitebricksModule.java:82) (via modules: com.myapp.servlet.MyGuiceServletConfig$1 -> com.google.inject.multibindings.Multibinder$RealMultibinder)
2) No implementation for java.util.Set<com.google.sitebricks.conversion.Converter> was bound.
at com.google.sitebricks.SitebricksModule.configure(SitebricksModule.java:82) (via modules: com.myapp.servlet.MyGuiceServletConfig$1 -> com.google.inject.multibindings.Multibinder$RealMultibinder)
2 errors
at com.google.inject.internal.Errors.throwCreationExceptionIfErrorsExist(Errors.java:448)
at com.google.inject.internal.InternalInjectorCreator.initializeStatically(InternalInjectorCreator.java:155)
at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:107)
at com.google.inject.Guice.createInjector(Guice.java:96)
at com.google.inject.Guice.createInjector(Guice.java:73)
at com.google.inject.Guice.createInjector(Guice.java:62)
at com.myapp.servlet.MyGuiceServletConfig.getInjector(MyGuiceServletConfig.java:13)
at com.google.inject.servlet.GuiceServletContextListener.contextInitialized(GuiceServletContextListener.java:47)
at org.mortbay.jetty.handler.ContextHandler.startContext(ContextHandler.java:548)
at org.mortbay.jetty.servlet.Context.startContext(Context.java:136)
at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1250)
at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:517)
at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:467)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
at com.google.apphosting.runtime.jetty.AppVersionHandlerMap.createHandler(AppVersionHandlerMap.java:199)
at com.google.apphosting.runtime.jetty.AppVersionHandlerMap.getHandler(AppVersionHandlerMap.java:174)
at com.google.apphosting.runtime.jetty.JettyServletEngineAdapter.serviceRequest(JettyServletEngineAdapter.java:134)
at com.google.apphosting.runtime.JavaRuntime$RequestRunnable.run(JavaRuntime.java:527)
at com.google.tracing.TraceContext$TraceContextRunnable.runInContext(TraceContext.java:437)
at com.google.tracing.TraceContext$TraceContextRunnable$1.run(TraceContext.java:444)
at com.google.tracing.CurrentContext.runInContext(CurrentContext.java:220)
at com.google.tracing.TraceContext$AbstractTraceContextCallback.runInInheritedContextNoUnref(TraceContext.java:308)
at com.google.tracing.TraceContext$AbstractTraceContextCallback.runInInheritedContext(TraceContext.java:300)
at com.google.tracing.TraceContext$TraceContextRunnable.run(TraceContext.java:441)
at com.google.apphosting.runtime.ThreadGroupPool$PoolEntry.run(ThreadGroupPool.java:251)
at java.lang.Thread.run(Thread.java:724)
Caused by: java.lang.SecurityException: Unable to get members for class com.google.inject.multibindings.Multibinder$RealMultibinder
at com.google.appengine.runtime.Request.process-67803a1bdc416a76(Request.java)
at java.lang.Class.getDeclaredFields(Class.java:218)
at com.google.inject.spi.InjectionPoint.getInjectionPoints(InjectionPoint.java:661)
at com.google.inject.spi.InjectionPoint.forInstanceMethodsAndFields(InjectionPoint.java:366)
at com.google.inject.spi.InjectionPoint.forInstanceMethodsAndFields(InjectionPoint.java:385)
at com.google.inject.internal.BindingBuilder.toProvider(BindingBuilder.java:110)
at com.google.inject.internal.BindingBuilder.toProvider(BindingBuilder.java:100)
at com.google.inject.internal.BindingBuilder.toProvider(BindingBuilder.java:43)
at com.google.inject.multibindings.Multibinder$RealMultibinder.configure(Multibinder.java:269)
at com.google.inject.spi.Elements$RecordingBinder.install(Elements.java:253)
at com.google.inject.multibindings.Multibinder.newSetBinder(Multibinder.java:115)
at com.google.inject.multibindings.Multibinder.newSetBinder(Multibinder.java:124)
at com.google.sitebricks.SitebricksModule.configure(SitebricksModule.java:82)
at com.google.inject.AbstractModule.configure(AbstractModule.java:62)
at com.google.inject.spi.Elements$RecordingBinder.install(Elements.java:253)
at com.google.inject.spi.Elements.getElements(Elements.java:108)
at com.google.inject.internal.InjectorShell$Builder.build(InjectorShell.java:135)
at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:104)
at com.google.inject.Guice.createInjector(Guice.java:96)
at com.google.inject.Guice.createInjector(Guice.java:73)
at com.google.inject.Guice.createInjector(Guice.java:62)
at com.myapp.servlet.MyGuiceServletConfig.getInjector(MyGuiceServletConfig.java:13)
at com.google.inject.servlet.GuiceServletContextListener.contextInitialized(GuiceServletContextListener.java:47)
at org.mortbay.jetty.handler.ContextHandler.startContext(ContextHandler.java:548)
at org.mortbay.jetty.servlet.Context.startContext(Context.java:136)
at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1250)
at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:517)
at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:467)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
at com.google.tracing.TraceContext$TraceContextRunnable.runInContext(TraceContext.java:437)
at com.google.tracing.TraceContext$TraceContextRunnable$1.run(TraceContext.java:444)
at com.google.tracing.CurrentContext.runInContext(CurrentContext.java:220)
at com.google.tracing.TraceContext$AbstractTraceContextCallback.runInInheritedContextNoUnref(TraceContext.java:308)
at com.google.tracing.TraceContext$AbstractTraceContextCallback.runInInheritedContext(TraceContext.java:300)
at com.google.tracing.TraceContext$TraceContextRunnable.run(TraceContext.java:441)
... 1 more
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
... 35 more
Caused by: java.lang.NoClassDefFoundError: Lcom/google/inject/internal/util/$ImmutableList;
at java.lang.Class.getDeclaredFields0(Native Method)
at java.lang.Class.privateGetDeclaredFields(Class.java:2383)
... 35 more
Caused by: java.lang.ClassNotFoundException: com.google.inject.internal.util.$ImmutableList
at com.google.appengine.runtime.Request.process-67803a1bdc416a76(Request.java)
... 35 more
在我看来,com.google.inject.util.internal 包在 4.0-beta5 中完全缺失,这就是导致 ClassNotFoundException 的原因。使用 3.0 而不是 4.0-beta5 解决了这个问题。
是否有可能以某种方式使用两者的最新版本?考虑到两者都是“谷歌出生的项目”,我很惊讶它们不兼容。有没有比 Sitebricks 更好的替代品?
PS 附带说明,sitebricks.org 已关闭,尽管最近(2015 年 1 月)有一些提交......该项目是否仍在积极维护?