播放框架注入错误

时间:2016-07-09 04:04:55

标签: java jpa playframework

我正在尝试使用Play 2.5将JPAApi注入我的控制器,但我一直得到以下异常。

com.google.inject.ProvisionException:无法配置,请参阅以下错误:

1) Error injecting constructor, java.lang.NoClassDefFoundError: org/dom4j/io/STAXEventReader
  at play.db.jpa.DefaultJPAApi$JPAApiProvider.<init>(DefaultJPAApi.java:39)
  at play.db.jpa.DefaultJPAApi$JPAApiProvider.class(DefaultJPAApi.java:34)
  while locating play.db.jpa.DefaultJPAApi$JPAApiProvider
  while locating play.db.jpa.JPAApi
    for parameter 0 at controllers.HomeController.<init>(HomeController.java:20)
  while locating controllers.HomeController
    for parameter 1 at router.Routes.<init>(Routes.scala:40)
  while locating router.Routes
  while locating play.api.inject.RoutesProvider
  while locating play.api.routing.Router
    for parameter 0 at play.api.http.JavaCompatibleHttpRequestHandler.<init>(HttpRequestHandler.scala:200)
  while locating play.api.http.JavaCompatibleHttpRequestHandler
  while locating play.api.http.HttpRequestHandler
    for parameter 4 at play.api.DefaultApplication.<init>(Application.scala:221)
  at play.api.DefaultApplication.class(Application.scala:221)
  while locating play.api.DefaultApplication
  while locating play.api.Application

1 error
     com.google.inject.internal.InjectorImpl$2.get(InjectorImpl.java:1025)
     com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1051)
     play.api.inject.guice.GuiceInjector.instanceOf(GuiceInjectorBuilder.scala:405)
     play.api.inject.guice.GuiceInjector.instanceOf(GuiceInjectorBuilder.scala:400)
     play.api.inject.guice.GuiceApplicationBuilder.build(GuiceApplicationBuilder.scala:123)
     play.api.inject.guice.GuiceApplicationLoader.load(GuiceApplicationLoader.scala:21)
     play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1$$anonfun$1$$anonfun$2.apply(DevServerStart.scala:158)
     play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1$$anonfun$1$$anonfun$2.apply(DevServerStart.scala:155)
     play.utils.Threads$.withContextClassLoader(Threads.scala:21)
     play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1$$anonfun$1.apply(DevServerStart.scala:155)
     play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1$$anonfun$1.apply(DevServerStart.scala:126)
     scala.Option.map(Option.scala:146)
     play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1.apply(DevServerStart.scala:126)
     play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1.apply(DevServerStart.scala:124)
     scala.util.Success.flatMap(Try.scala:231)
     play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1.apply(DevServerStart.scala:124)
     play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1.apply(DevServerStart.scala:116)
     scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24)
     scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24)
     java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1402)
     java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
     java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
     java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
     java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)

这是我的控制器。

public class HomeController extends Controller {

    private JPAApi jpaApi;

    @Inject
    public HomeController(JPAApi jpaApi) {
        this.jpaApi = jpaApi;
    }

    public Result index() {
        jpaApi.withTransaction(entityManager -> {
            Query query = entityManager.createNativeQuery("select max(age) from people");
            return (Long) query.getSingleResult();
        });
        return ok(index.render("Your new application is ready."));
    }

}

2 个答案:

答案 0 :(得分:7)

你刚刚碰到sbt中的一个错误(Play正在使用的构建工具)。 这个bug引起了Hibernate版本5.2.1(但不是5.2.0)。

Hibernate 5.2.1开始使用dom4j maven无法处理的sbt语法排除"dom4j" % "dom4j" % "1.6.1" intransitive() 的所有传递依赖项。

现在的解决方法是添加

libraryDependencies

build.sbt中的sbt(与Hibernate依赖项并行)。

有关更详细的信息,请查看sbt错误本身,可在此处找到:https://github.com/sbt/sbt/issues/1431

我报告的Hibernate错误(但已被关闭,因为它原来是一个getWritableDatabase()问题)可以在这里找到: https://hibernate.atlassian.net/browse/HHH-10916

答案 1 :(得分:0)

基于您提供的小代码片段,我假设您正在使用Play Java API。假设尽可能多,我首先建议您参考关于依赖注入的Play documentation

如果您使用其中一个Activator模板引导项目,您可能最终得到以下两个文件(以及其他许多文件):

.
├── app
│   ├── Module.java
└── conf
    └── application.conf

“模块”是在Guice中配置绑定的一种方法(基本上当组件请求注入给定类型时Guice将提供服务)。

为了让你在此期间开始运作......

...首先,在 play.modules 部分下的application.conf文件中,取消注释要添加到启用的模块集的行,这样你最终会得到一些东西像这样:

play.modules {
    enabled += Module
}

...接下来,假设您有一个名为JPAApi的接口,其具体实现JPAApiImpl ...更新Module.java,如下所示:

import com.google.inject.AbstractModule;

public class Module extends AbstractModule {
    @Override
    public void configure() {
        bind(JPAApi.class).to(JPAApiImpl.class);
    }
}

(或者如果JPAApi本身就是一个具体的实现,你可以将它绑定到自身)

重新启动你的应用程序并注入你的控制器。