How can SBT generate metamodel classes from model classes using DataNucleus?

我们两清 提交于 2019-12-14 02:33:10

问题


How can I generate metamodel classes (like QClient, QProduct, QInvoice) from a persistence model classes (like Client, Product, Invoice) so that a JDOQL typesafe queries can be employed?

In particular, I'm interested on generating the metamodel classes and also run bytecode enhancement on persistence classes, via SBT and using DataNucleus with JDO annotations.


This question is related to
How can I run DataNucleus Bytecode Enhancer from SBT?


回答1:


In a nutshell, you need to define functions in your build.sbt which perform the generation of the metamodel and bytecode enhancement, like shown below:

def generateQueryEntities(sourcepath: File,
                          sources: Seq[File],
                          generated: File,
                          classes: File,
                          classpath: Seq[File],
                          javacOptions: Seq[String]): Seq[File] = {
  IO.createDirectory(generated)
  javaRunner(
    javaTool = Option("javac"),
    args =
      javacOptions ++
        (if(debug) Seq("-verbose") else Seq.empty[String]) ++
        Seq(
          "-sourcepath", sourcepath.absolutePath,
          "-s",  generated.absolutePath,
          "-d",  classes.absolutePath) ++
        sources.map(p => p.absolutePath),
    classpath = Option(classpath),
    cwd = Option(classes)
  )
  classes.listFiles.filter(f => f.isFile && (f.ext == "class"))
}

def enhanceSchema(classes: File, classpath: Seq[File]): Seq[File] = {
  javaRunner(
    mainClass = Option("javax.jdo.Enhancer"),
    args =
      (if(debug) Seq("-v") else Seq.empty[String]) ++
      Seq(
        "-pu", "code-generation",
        "-d",  classes.absolutePath),
    classpath = Option(classpath),
    cwd = Option(classes)
  )
  classes.listFiles.filter(f => f.isFile && (f.ext == "class"))
}

The next step consists on defining custom tasks for these functions. We need only genjdoql as shown below since the bytecode enhancement can be wired via sub-task manipulateBytecode. Notice that SBT 0.13.8 or greater is required.

val genjdoql      = TaskKey[Seq[File]]("genjdoql",    "DataNucleus JDOQL Entities")

Then you need to wire these functions in the build of your project or module, like shown below:

lazy val model =
  project.in(file("model"))
    .settings(publishSettings:_*)
    .settings(librarySettings:_*)
    .settings(paranoidOptions:_*)
    .settings(otestFramework: _*)
    .settings(deps_resolvers:_*)
    //XXX .settings(deps_langtools:_*)
    .settings(deps_tagging:_*)
    .settings(deps_stream:_*)
    .settings(deps_database:_*)
    .settings(managedSources:_*)
    .settings(
      Seq(
        // generate JDOQL Entities
        genjdoql in Compile := {
          generateQueryEntities(
            sourcepath = (javaSource in Compile).value,
            sources = (unmanagedSources in Compile).value,
            generated = baseDirectory.value / "target" / scalav(scalaVersion.value) / "src_managed" / "main"  / "java",
            classes = (classDirectory in Compile).value,
            classpath = (managedClasspath in Compile).value.files,
            javacOptions = javacOpts :+ "-AqueryMode=PROPERTY"
          )},
        sourceGenerators in Compile <+= genjdoql in Compile,
        // prevent javac from running annotation processors
        javacOptions ++= Seq( "-proc:none" ),
        // perform bytecode enhancement
        manipulateBytecode in Compile := {
          val previous = (manipulateBytecode in Compile).value
          enhanceSchema(
            classes = (classDirectory in Compile).value,
            classpath =
              (managedClasspath in Compile).value.files ++
                (unmanagedResourceDirectories in Compile).value :+
                (classDirectory in Compile).value)
          previous
        }
      ):_*)
    .dependsOn(util)

For a complete example, please have a look at
https://github.com/frgomes/poc-scala-datanucleus



来源:https://stackoverflow.com/questions/30401746/how-can-sbt-generate-metamodel-classes-from-model-classes-using-datanucleus

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!