Java 如何使用 gradle、jaxb 和 xjc 从 xsd 生成 jaxb 类,类应该有 XmlRootElement
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/41880496/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to generate jaxb classes from xsd using gradle, jaxb and xjc, classes should have XmlRootElement
提问by aamir
We were trying to generate JAXB classes using gradle, xsd and xjc, and JAXB classes should have XmlRootElement annotations so it could be used to expose as web service reponse. We were following this link http://azagorneanu.blogspot.com/2011/09/configure-maven-to-generate-classes.html, it helped in great deal but we were unable to find one particular example with gradle only. So we figured out few things what we will share as an answer.
我们尝试使用 gradle、xsd 和 xjc 生成 JAXB 类,并且 JAXB 类应该具有 XmlRootElement 注释,以便它可以用于作为 Web 服务响应公开。我们正在关注此链接http://azagorneanu.blogspot.com/2011/09/configure-maven-to-generate-classes.html,它有很大帮助,但我们无法找到一个仅使用 gradle 的特定示例。因此,我们想出了一些我们将作为答案分享的内容。
回答by aamir
build.gradle should look like below
build.gradle 应该如下所示
buildscript {
repositories {
mavenCentral()
jcenter()
}
dependencies {
classpath "net.saliman:gradle-cobertura-plugin:2.2.4"
classpath 'com.github.jacobono:gradle-jaxb-plugin:1.3.5'
}
}
apply plugin: 'com.github.jacobono.jaxb'
dependencies {
jaxb 'com.sun.xml.bind:jaxb-xjc:2.2.7'
jaxb "org.jvnet.jaxb2_commons:jaxb2-basics-ant:0.6.5"
jaxb "org.jvnet.jaxb2_commons:jaxb2-basics:0.6.4"
jaxb "org.jvnet.jaxb2_commons:jaxb2-basics-annotate:0.6.4"
}
configurations {
jaxb
}
task jaxb(){
description 'Converts xsds to classes'
def jaxbTargetDir = file("generated")
doLast {
jaxbTargetDir.mkdirs()
ant.taskdef(name: 'xjc', classname: 'org.jvnet.jaxb2_commons.xjc.XJC2Task', classpath: configurations.jaxb.asPath)
ant.jaxbTargetDir = jaxbTargetDir
ant.xjc(destdir: '${jaxbTargetDir}', package: 'com.sample.jaxbclasses', schema:'generated/schema.xsd', binding:'generated/binding.xjb', extension:'true'){
arg(value: "-Xannotate")
}
}
}
schema.xsd
架构.xsd
<xs:element name="user" type="user" />
<xs:element name="userList" type="userList" />
<xs:complexType name="user">
<xs:all>
<xs:element name="id" type="xs:long" minOccurs="0" />
<xs:element name="name" type="xs:string" />
<xs:element name="registrationDate" type="xs:dateTime" />
</xs:all>
</xs:complexType>
<xs:complexType name="userList">
<xs:sequence>
<xs:element name="user" type="user" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:schema>
binding.xjb
绑定.xjb
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:annox="http://annox.dev.java.net"
xsi:schemaLocation="http://java.sun.com/xml/ns/jaxb http://java.sun.com/xml/ns/jaxb/bindingschema_2_0.xsd"
version="2.1">
<jaxb:globalBindings>
<!-- Use java.util.Calendar instead of javax.xml.datatype.XMLGregorianCalendar for xs:dateTime -->
<jaxb:javaType name="java.util.Calendar" xmlType="xs:dateTime"
parseMethod="javax.xml.bind.DatatypeConverter.parseDateTime"
printMethod="javax.xml.bind.DatatypeConverter.printDateTime" />
<!-- Force all classes implements Serializable -->
<xjc:serializable uid="1" />
</jaxb:globalBindings>
<!-- Annotate the following classes with XmlRootElement -->
<jaxb:bindings schemaLocation="schema.xsd" node="/xs:schema">
<jaxb:bindings node="xs:complexType[@name='user']">
<annox:annotate>
<annox:annotate annox:class="javax.xml.bind.annotation.XmlRootElement" name="user" />
</annox:annotate>
</jaxb:bindings>
<jaxb:bindings node="xs:complexType[@name='userList']">
<annox:annotate>
<annox:annotate annox:class="javax.xml.bind.annotation.XmlRootElement" name="userList" />
</annox:annotate>
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
below binding.xjb could be used as well
下面的 binding.xjb 也可以使用
<?xml version="1.0"?>
<jxb:bindings version="1.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" jxb:extensionBindingPrefixes="xjc" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<jxb:bindings schemaLocation="schema.xsd" node="/xs:schema">
<jxb:globalBindings>
<xjc:simple />
</jxb:globalBindings>
</jxb:bindings>
</jxb:bindings>
Now you can run the task 'jaxb', All set. Cheers!
现在您可以运行任务 ' jaxb',全部设置。干杯!
User.java
用户.java
//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.7
// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
// Any modifications to this file will be lost upon recompilation of the source schema.
// Generated on: 2017.01.26 at 11:59:18 AM EST
//
package com.sample.jaxbclasses;
import java.io.Serializable;
import java.util.Calendar;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSchemaType;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
/**
* <p>Java class for user complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* <complexType name="user">
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <all>
* <element name="id" type="{http://www.w3.org/2001/XMLSchema}long" minOccurs="0"/>
* <element name="name" type="{http://www.w3.org/2001/XMLSchema}string"/>
* <element name="registrationDate" type="{http://www.w3.org/2001/XMLSchema}dateTime"/>
* </all>
* </restriction>
* </complexContent>
* </complexType>
* </pre>
*
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "user", propOrder = {
})
@XmlRootElement(name = "user")
public class User
implements Serializable
{
private final static long serialVersionUID = 1L;
protected Long id;
@XmlElement(required = true)
protected String name;
@XmlElement(required = true, type = String.class)
@XmlJavaTypeAdapter(Adapter1 .class)
@XmlSchemaType(name = "dateTime")
protected Calendar registrationDate;
/**
* Gets the value of the id property.
*
* @return
* possible object is
* {@link Long }
*
*/
public Long getId() {
return id;
}
/**
* Sets the value of the id property.
*
* @param value
* allowed object is
* {@link Long }
*
*/
public void setId(Long value) {
this.id = value;
}
/**
* Gets the value of the name property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getName() {
return name;
}
/**
* Sets the value of the name property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setName(String value) {
this.name = value;
}
/**
* Gets the value of the registrationDate property.
*
* @return
* possible object is
* {@link String }
*
*/
public Calendar getRegistrationDate() {
return registrationDate;
}
/**
* Sets the value of the registrationDate property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setRegistrationDate(Calendar value) {
this.registrationDate = value;
}
}
回答by grep
group 'com.example'
version '1.0-SNAPSHOT'
apply plugin: 'java'
sourceCompatibility = 1.8
targetCompatibility = 1.8
repositories {
mavenCentral()
}
project.ext {
jaxbTargetDir = file("src/generated/java")
}
configurations {
xsd2java
}
dependencies {
xsd2java "com.sun.xml.bind:jaxb-xjc:2.2.6"
xsd2java "com.sun.xml.bind:jaxb-impl:2.2.6"
}
task xsd2java() {
doLast {
jaxbTargetDir.mkdirs()
ant.taskdef(name: 'xjc', classname: 'com.sun.tools.xjc.XJCTask', classpath: configurations.xsd2java.asPath)
ant.jaxbTargetDir = jaxbTargetDir
ant.xjc(
destdir: '${jaxbTargetDir}',
package: 'com.example.request',
schema: 'src/main/resources/XMLreq.xsd'
)
ant.xjc(
destdir: '${jaxbTargetDir}',
package: 'com.example.response',
schema: 'src/main/resources/XMLres.xsd'
)
}
}
compileJava.dependsOn xsd2java
回答by Antonio Maria Sanchez Berrocal
My version use gradle native feature to generate jaxbclasses.
我的版本使用 gradle 本机功能来生成 jaxbclasses。
Optionally, if case your schema depends on external xsd(s), use "Oasis Catalog" technique to resolve external XSD locally. Also in this case disable XML schema validations to prevent validation errors.
或者,如果您的架构依赖于外部 xsd,请使用“Oasis Catalog”技术在本地解析外部 XSD。同样在这种情况下,禁用 XML 架构验证以防止验证错误。
Optionally you can adjust your jaxbclasses with a custom jaxb binding. (Jaxb-bindings.xjb)
或者,您可以使用自定义 jaxb 绑定调整您的 jaxbclasses。(Jaxb-bindings.xjb)
Basically is a gradle custom task, which invoke the XJCTask ant task available in Java VM, in my example libraries are from Java 8. Task name is "generateSources", and need to be adjusted to your schema location.
基本上是一个 gradle 自定义任务,它调用 Java VM 中可用的 XJCTask ant 任务,在我的示例库中来自 Java 8。任务名称是“generateSources”,需要根据您的模式位置进行调整。
configurations {
jaxb // Only for generation purpose
}
dependencies {
jaxb 'javax.xml.bind:jaxb-api:2.2.11'
jaxb 'com.sun.xml.bind:jaxb-xjc:2.2.11'
jaxb 'com.sun.xml.bind:jaxb-impl:2.2.11'
jaxb 'com.sun.xml.bind:jaxb-osgi:2.2.11'
}
task generateSources() {
doLast {
def jaxbTargetDir = file("$buildDir/generated/src/main/java")
if (!jaxbTargetDir.exists()) {
jaxbTargetDir.mkdirs()
}
ant.taskdef(name: 'xjc', classname: 'com.sun.tools.xjc.XJCTask', classpath: configurations.jaxb.asPath)
ant.xjc(
destdir: "${jaxbTargetDir}",
schema: "${projectDir}/src/main/resources/MySchema.xsd",
binding: "${projectDir}/src/main/resources/jaxb-bindings.xjb",
catalog: "${projectDir}/src/main/resources/catalog.xml",
removeOldOutput: 'yes', extension: 'true'
)
{
arg(line: '-nv -disableXmlSecurity')
}
}
}
In case you need catalog create a file "catalog.xml" which might look like this:
如果您需要目录,请创建一个文件“catalog.xml”,它可能如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE catalog
PUBLIC "-//OASIS//DTD Entity Resolution XML Catalog V1.0//EN"
"http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd">
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
<system systemId="http://www.w3.org/TR/2002/REC-xmlenc-core-20021210/xenc-schema.xsd" uri="xenc-schema.xsd" />
<system systemId="http://www.w3.org/TR/xmlenc-core/xenc-schema.xsd" uri="xenc-schema.xsd" />
<system systemId="http://www.w3.org/TR/2002/REC-xmldsig-core-20020212/xmldsig-core-schema.xsd" uri="xmldsig-core-schema.xsd" />
</catalog>
For jaxbinding
对于 jaxbinding
<?xml version="1.0" encoding="UTF-8"?>
<bindings xmlns="http://java.sun.com/xml/ns/jaxb" version="2.1"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<globalBindings>
<xjc:javaType
adapter="org.gazpachoquest.sample.JodaLocalDateTimeConverter"
name="org.joda.time.LocalDateTime" xmlType="xs:dateTime" />
</globalBindings>
</bindings>
If in addition to jaxb generation, you need to include those classes to build. You need to adjust gradle source layout, and dependencies.
如果除了 jaxb 生成之外,还需要包含这些类来构建。您需要调整 gradle 源布局和依赖项。
apply plugin: 'java'
def generatedSourcesOutput = "$buildDir/generated/main/java"
sourceSets {
main {
java.srcDirs "$generatedSourcesOutput"
}
}
configurations {
jaxb
}
dependencies {
jaxb 'javax.xml.bind:jaxb-api:2.2.11'
jaxb 'com.sun.xml.bind:jaxb-xjc:2.2.11'
jaxb 'com.sun.xml.bind:jaxb-impl:2.2.11'
jaxb 'com.sun.xml.bind:jaxb-osgi:2.2.11'
compile 'com.sun.xml.bind:jaxb-xjc:2.2.11'
compile 'com.sun.xml.bind:jaxb-impl:2.2.11'
compile 'javax.xml.bind:jaxb-api:2.2.11'
}
compileJava {
dependsOn generateSources
}
That's all!
就这样!
回答by sweetfa
Gradle configuration for using gradle-jaxb-plugin
使用gradle-jaxb-plugin 的Gradle 配置
The commented out values in the xjc configuration are the default values - change if required.
xjc 配置中注释掉的值是默认值 - 如果需要可以更改。
buildscript {
repositories gradle.repos
dependencies {
}
}
plugins {
id "org.openrepose.gradle.plugins.jaxb" version "2.5.0"
id 'groovy'
id 'java'
id "org.springframework.boot" version "2.1.2.RELEASE"
id 'checkstyle'
}
apply plugin: 'io.spring.dependency-management'
apply plugin: "org.openrepose.gradle.plugins.jaxb"
apply plugin: 'idea'
apply plugin: 'maven-publish'
repositories gradle.repos
configurations {
jaxb
codeq
compile.exclude module: "spring-boot-starter-tomcat"
}
jaxb {
xjc {
//taskClassname = 'com.sun.tools.xjc.XJC2Task'
//xsdDir = "${project.projectDir}/src/main/resources/schema"
generateEpisodeFiles = false
generatePackage = 'com.mycompany.mypackage'
destinationDir = "${buildDir}/generated/src/main/java"
args = ["-Xannotate"]
}
}
compileJava.dependsOn {
'xjc'
}
sourceSets {
main {
java {
srcDirs jaxb.xjc.destinationDir
}
resources {
srcDirs 'src/main/resources'
}
}
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudDependenciesVersion}"
}
}
dependencies {
// Jaxb dependencies
jaxb group: 'org.glassfish.jaxb', name: 'jaxb-xjc', version: jaxbxjcVersion
jaxb 'org.jvnet.jaxb2_commons:jaxb2-basics-annotate:1.0.4'
jaxb 'org.slf4j:slf4j-log4j12:1.7.25'
implementation group: 'javax.xml.bind', name: 'jaxb-api', version: jaxbApiVersion
}
and gradle.properties file
和 gradle.properties 文件
# JAXB Processing Properties
jaxbPluginVersion = 2.5.0
jaxbxjcVersion = 2.3.2
jaxbApiVersion = 2.3.1
and to link it with Intellij add the following to your build.gradle file
并将其与 Intellij 链接,将以下内容添加到您的 build.gradle 文件中
idea.module.iml {
whenMerged {
dependsOn jaxb
}
}
回答by Bienvenido David
I've been using the Spring Boot Producing a SOAP web serviceguide for reference. Here's the link to the build.gradle file in GitHub.
我一直在使用 Spring Boot Producing a SOAP web serviceguide 作为参考。这是 GitHub 中 build.gradle 文件的链接。
https://github.com/spring-guides/gs-producing-web-service/blob/master/complete/build.gradle
https://github.com/spring-guides/gs-production-web-service/blob/master/complete/build.gradle
回答by Martin Traverse
Here is a solution that works for me with Java 11 / Gradle 6. After updating the build system on one of my projects recently I found some issues using XJC via Ant tasks in Gradle - this approach just uses plain Gradle, without Ant.
这是一个适用于 Java 11/Gradle 6 的解决方案。最近在我的一个项目上更新构建系统后,我发现通过 Gradle 中的 Ant 任务使用 XJC 存在一些问题 - 这种方法只使用普通 Gradle,没有 Ant。
UPDATE: Using the GlassFish implementation avoids issues with Sun internal dependencies, as per this question
更新:根据这个问题,使用 GlassFish 实现避免了 Sun 内部依赖的问题
sourceSets {
generated {
java.srcDir "$generated_dir"
}
}
dependencies {
compile sourceSets.generated.output
// Generated code depends on the JAXB API, which is removed from base Java in JDK 11
compile "org.glassfish.jaxb:jaxb-runtime:2.3.3"
generatedCompile "org.glassfish.jaxb:jaxb-runtime:2.3.3"
}
// XJC tasks
// JAXB configuration holds classpath for running the JAXB XJC compiler
configurations {
jaxb
}
dependencies {
jaxb "org.glassfish.jaxb:jaxb-xjc:2.3.3"
}
// Cookie cutter function for defining multiple XJC tasks
// (not necessary if you only have a single task)!
def addXjcTask(taskName, schema, pkg, dest) {
// If you haven't already, create the generated output dir before running XJC or it will fail
file(dest).mkdirs()
// The main XJC task, calls XJCFacade which is the entry point of the XJC JAR
tasks.create(name: taskName, type: JavaExec) {
classpath configurations.jaxb
main 'com.sun.tools.xjc.XJCFacade'
// To explore available args, download the XJC JAR manually and run java -jar jaxb-xjc.jar --help
args schema, "-p", pkg, "-d", dest
}
// Add a dependency on the new task so it gets invoked
compileGeneratedJava.dependsOn tasks.getByName(taskName)
}
// Add all the XJC tasks you need
addXjcTask("xjcSchema1",
"path/to/schema1.xsd",
'com.example.generated.schema1',
"$generated_dir")
addXjcTask("xjcSchema2",
"path/to/schema2.xsd",
'com.example.generated.schema2',
"$generated_dir")