【问题标题】:Using PlayFramework + Ebean with Gradle在 Gradle 中使用 PlayFramework + Ebean
【发布时间】:2015-09-09 11:40:26
【问题描述】:

我正在尝试使用 Play Gradle Plugin 编译/打包使用 Ebean 的 Play 2.3.x 应用程序。

在编译和打包过程中一切正常,但是当我运行应用程序时出现众所周知的错误

Entity type class SomeEntity is not an enhanced entity bean. 
Subclassing is not longer supported in Ebean

那么我怎样才能让 Gradle 在编译期间运行增强器呢?

【问题讨论】:

    标签: gradle playframework ebean


    【解决方案1】:

    我就是这样做的。我正在使用 play 2.4,但应该可以为您工作。

    首先在你的 build.gradle 中添加如下配置 -

    configurations {
        enhance
    }
    

    接下来添加对ebeanorm代理的依赖,如下图:

    dependencies {
        enhance group: 'org.avaje.ebeanorm', name: 'avaje-ebeanorm-agent', version: '4.5.3'
    }
    

    确保您的 build.gradle 中有所需的播放依赖项,如下所示:

    dependencies {
        play 'org.avaje:avaje-agentloader:2.1.2'
        play "org.avaje.ebeanorm:avaje-ebeanorm-agent:4.5.3"
    }
    

    在编译任务执行后,最后添加以下内容进行增强:

    model {
        components {
            play {
                binaries.all{binary ->
                    tasks.withType(PlatformScalaCompile) {
                        doLast {
                            ant.taskdef(name: 'ebean', classname: 'com.avaje.ebean.enhance.ant.AntEnhanceTask', classpath: project.configurations.enhance.asPath)
                            ant.ebean(classSource: "${project.buildDir}/playBinary/classes", packages: 'models.package.name', transformArgs: 'debug=1')
    
                        }
                    }
                }
            }
        }
    

    【讨论】:

    • 嗨,我正在将 play 2.5.2 从 sbt 转换为 gradle。您的解决方案对我有用,一个问题是,它没有返回关系对象。我的意思是包含连接表的嵌套对象。对于关系对象,它返回 null。
    【解决方案2】:

    @koolrich,我已经尝试过解决方案,当它没有编译时,我继续前进,后来才发现唯一的问题是 dbmodels/* 预期路径,而我的路径不同。

    最初似乎是关于增强功能的魔术和令人困惑的行话,以下内容帮助我理解了正在发生的事情: https://openjpa.apache.org/builds/1.2.3/apache-openjpa/docs/ref_guide_pc_enhance.html 本质上,增强是添加更多方法和属性来处理持久性。

    【讨论】:

      【解决方案3】:

      我正在将 Play 2.5.2 (Java) 项目从 sbt 转换为 gradle 并面临同样的问题,然后尝试使用 @koolrich 给出的解决方案。但效果不佳。一切都很好,但它未能返回关系对象的数据(它为关系对象返回 null)。然后我比较了sbt和gradle生成的增强字节码,找出delta。然后找出该剧如何增强字节码。分三步播放增强字节码。

      • 它为尚未到位的字段生成 getter 和 setter,由 play-enhancements-plugins(play.core.enhancers.PropertiesEnhancer.generateAccessors) 完成
      • 它重写直接访问字段的类以使用访问器,并由 play-enhancements-plugins(play.core.enhancers.PropertiesEnhancer.rewriteAccess) 完成
      • 如果使用 Ebean,Ebean 增强器将应用于通过 application.conf 配置的类(ebean-enhancement 插件)

      示例:

      Employee employee=Employee.find.byId(1);
      Company company=employee.company;
      
      After Step 1&2, this will be converted to
      
      Company company=employee.getCompany();
      
      With Employee#getCompany() being something like
      
      @PropertiesEnhancer.GeneratedAccessor
      public Company getCompany(){
      return this.company;
      }
      
      After step 3, the getter will be modified to be something like
      
      @PropertiesEnhancer.GeneratedAccessor
      public Company getCompany(){
      return _ebean_get_company();
      }
      
      protected Company _ebean_get_company() {
        this._ebean_intercept.preGetter("company");
        return this.company;
      }
      

      所以将 sbt 转换为 gradle,你必须执行这三个步骤,因为 gradle play 插件不支持这三个步骤。对于第 3 步,ebean 具有可以使用的增强类(ant Task)(@koolrich 给出的解决方案),对于第 1 步和第 2 步,我编写了另一个增强 ant Task,它添加了访问器和重写访问权限。这是 gradle.build 文件的样子。

      configurations {
          enhance
          playEnhance
      }
      
      dependencies {
          enhance "org.avaje.ebeanorm:avaje-ebeanorm-agent:4.9.1"
          playEnhance 'com.typesafe.play:play-enhancer:1.1.0'
      }
      
      model {
          components {
              play {
                  binaries.all{binary ->
                      tasks.withType(PlatformScalaCompile) {
                          doLast {
                              ant.taskdef(name: "playenhancetask", classname:"com.xxx.gradlehelper.PlayGradleEnhancherTask", classpath:"${project.buildDir}/playBinary/classes/:${project.configurations.playEnhance.asPath}")
                              ant.playenhancetask(classSource: "${project.buildDir}/playBinary/classes", packages: 'com.xxx.xxx.*', classpath:"${project.configurations.play.asPath}")
                              ant.taskdef(name: 'ebean', classname: 'com.avaje.ebean.enhance.ant.AntEnhanceTask', classpath: project.configurations.enhance.asPath)
                              ant.ebean(classSource: "${project.buildDir}/playBinary/classes", packages: 'com.xxx.xxx.xxx.*', transformArgs: 'debug=1')
                          }
                      }
                  }
              }
          }
      }
      
      dependencies {
          play 'org.avaje:avaje-agentloader:2.1.2'
          play 'org.avaje.ebeanorm:avaje-ebeanorm:6.18.1'
          play 'com.typesafe.play:play-ebean_2.11:3.0.0'
          play 'com.typesafe.play:play-enhancer:1.1.0'
          play "org.avaje.ebeanorm:avaje-ebeanorm-agent:4.9.1"
          play group: 'org.apache.ant', name: 'ant', version: '1.8.2'
      }
      

      这是我的 ant 任务 PlayGradleEnhancherTask.java

      package com.xxx.gradlehelper;
      
      import org.apache.tools.ant.BuildException;
      import org.apache.tools.ant.Task;
      import play.core.enhancers.*;
      
      import java.io.File;
      import java.io.IOException;
      import java.nio.file.DirectoryStream;
      import java.nio.file.Files;
      import java.nio.file.Path;
      import java.nio.file.Paths;
      import java.util.ArrayList;
      import java.util.List;
      
      public class PlayGradleEnhancherTask extends Task {
      
          String classpath;  
          String classSource;
          String transformArgs;
          String packages;
          public String getClasspath() {
              return classpath;
          }  
          public void setClasspath(String classpath) {
              this.classpath = classpath;
          }    
          public void setClassSource(String source) {
              this.classSource = source;
          }   
          public void setTransformArgs(String transformArgs) {
              this.transformArgs = transformArgs;
          }
      
          public void setPackages(String packages) {
              this.packages = packages;
          }  
          public void execute() {
              if (packages == null) {
                  throw new BuildException("No message set.");
              }
              log("classSource: " + classSource + ", packages: " + packages + "\n classPath: "+ classpath);
      
              String dir = packages.trim().replace('.', '/');
              dir = dir.substring(0, dir.length() - 1);
      
              String dirPath = classSource + "/" + dir;
              File d = new File(dirPath);
              if (!d.exists()) {
                  throw new RuntimeException("File not found " + dirPath + "  currentDir:" + new File(".").getAbsolutePath());
              }
      
              Path path = Paths.get(dirPath);
              List<File> fileNames = new ArrayList();
              List<File> files = getFiles(fileNames, path);
      
              //generate property accessor
              generateAccessors(files);
      
              //rewrite access
              rewriteAccess(files);
          }
      
          private void rewriteAccess(List<File> files) {
              for (File file: files) {
                  try{
                       PropertiesEnhancer.rewriteAccess(classSource+":"+classpath,file);
                  }catch (Exception e){
                      String fileName = file == null ? "null" : file.getName() +",  e: "+ e.getMessage();
                      System.err.println("Could not enhance[rewriteAccess]:"+fileName);
                  }
              }
          }
          private void generateAccessors(List<File> files) {
              for (File file: files) {
                  try{
                      PropertiesEnhancer.generateAccessors(classSource+":"+classpath,file);
                  }catch (Exception e){
                      e.printStackTrace();
                      String fileName = file == null ? "null" : file.getName();
                      System.err.println("Could not enhance[generateAccessors]: "+fileName);
                  }
              }
          }
      
          private List<File> getFiles(List<File> files, Path dir) {
              try(DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
                  for (Path path : stream) {
                      if(path.toFile().isDirectory()) {
                          getFiles(files, path);
                      } else {
                          File file = path.toFile();
                          if(!file.getName().startsWith("Reverse")&& file.getName().endsWith(".class")) {
                              files.add(file);
                          }
                      }
                  }
              } catch(IOException e) {
                  e.printStackTrace();
              }
              return files;
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多