Error when converting XSD to Java using jaxb - java

It has been some time since I used XSD, XML and JAXB. Now I'd like to use it again. Unfortunately I have a strange error that I cannot resolve.
Here is my build.gradle.
configurations {
jaxb
}
dependencies {
jaxb 'org.glassfish.jaxb:jaxb-xjc:2.3.6'
}
task genJaxb {
ext.sourcesDir = "${buildDir}/generated-sources/jaxb"
// that works!
// ext.schema = 'https://raw.githubusercontent.com/spring-guides/gs-producing-web-service/main/complete/src/main/resources/countries.xsd'
// that DOES NOT work!
ext.schema = 'https://cwe.mitre.org/data/xsd/cwe_schema_latest.xsd'
outputs.dir sourcesDir
doLast() {
project.ant {
taskdef(
name: 'xjc',
classname: 'com.sun.tools.xjc.XJCTask',
classpath: configurations.jaxb.asPath
)
mkdir(dir: sourcesDir)
xjc(destdir: sourcesDir, schema: schema)
}
}
}
My schema comes from Mitre https://cwe.mitre.org/data/xsd/cwe_schema_latest.xsd. The overall task should work as the result is fine for a different sample schema https://raw.githubusercontent.com/spring-guides/gs-producing-web-service/main/complete/src/main/resources/countries.xsd. Unfortunately I'm getting the following error when using the Mitre schema.
[ant:xjc] [ERROR] Property "Lang" is already defined. Use <jaxb:property> to resolve this conflict.
[ant:xjc] line 302 of http://www.w3.org/2002/08/xhtml/xhtml1-strict.xsd
[ant:xjc]
[ant:xjc] [ERROR] The following location is relevant to the above error
[ant:xjc] line 303 of http://www.w3.org/2002/08/xhtml/xhtml1-strict.xsd
I did some research and I sounds like I have to use some custom binding. However I do not even find "Lang" in the XSD file.
Any ideas how I can generate the Java code? Thank you very much!

Related

Generate classes from wsdl when path is /src/client/java

I am trying to generate classes from a wsdl file. My source root path does not includes main but client.
The root is src/client/java
my build.gradle:
plugins {
id "com.github.bjornvester.wsdl2java" version "1.2"
}
dependencies {
implementation "org.apache.cxf:cxf-spring-boot-starter-jaxws:3.5.3"
}
wsdl2java {
wsdlDir = file("src/client/resources/wsdl")
includes = [
"wsdl/QueryService.wsdl"
]
}
When I build the project, the build/generated/sources/wsdl2java/java[main] (it looks like this) is empty.
There is no error.
what am I doing wrong?

cxf-codegen-plugin in Gradle classpath in jax-ws-catalog.xml

Firstly idea was to generate java classes without internet connection, so I decided use jax-ws-catalog.xml file to rewrite uri on resource/local directory.
I defined location of xsd files by using jax-ws-catalog.xml with classpath.
But every compilation is wrong and catching error:
WARN org.apache.cxf.resource.URIResolver - Resource classpath:/local/xml.xsd was not found in the classloaders.
WSDLToJava Error: org.apache.ws.commons.schema.XmlSchemaException: Unable to locate imported document at 'http://www.w3.org/2001/xml.xsd', relative to ...{my file}...
build.gradle
plugins {
id 'java'
id 'java-library'
id "io.mateo.cxf-codegen" version "1.0.2"
}
import io.mateo.cxf.codegen.wsdl2java.Wsdl2Java
ext {
artifactId = 'soap-adapter'
}
jar {
enabled = true
}
bootJar {
enabled = false
}
dependencies {
implementation "javax.xml.ws:jaxws-api:${jaxwsApiVersion}"
implementation "javax.jws:javax.jws-api:${javaxJwsApiVersion}"
implementation "com.sun.xml.messaging.saaj:saaj-impl:${sunSaajImplVersion}"
implementation "org.apache.cxf:cxf-rt-frontend-jaxws:${apacheCxfVersion}"
implementation "org.apache.cxf:cxf-rt-transports-http:${apacheCxfVersion}"
implementation "org.apache.cxf:cxf-rt-ws-security:${apacheCxfVersion}"
cxfCodegen "jakarta.xml.ws:jakarta.xml.ws-api"
cxfCodegen "jakarta.annotation:jakarta.annotation-api"
cxfCodegen "ch.qos.logback:logback-classic"
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
// Common properties of java generation from wsdl.
tasks.withType(Wsdl2Java).configureEach {
toolOptions {
markGenerated.set(true)
outputDir.set(file("${buildDir}/generated"))
addToMainSourceSet.set(true)
wsdl.set(file("${projectDir}/src/main/resources/wsdl/myWsdl.wsdl"))
catalog.set("${projectDir}/src/main/resources/META-INF/jax-ws-catalog.xml")
}
}
compileJava.dependsOn wsdl2java
jax-ws-catalog.xml
<?xml version="1.0"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
<rewriteURI uriStartString="http://www.w3.org/2001/xml.xsd" rewritePrefix="classpath:/local/xml.xsd"/>
</catalog>
I think that classpath is determined wrong.
I discovered the next:
At the programm compilation jax-ws-catalog.xml using only relative paths from itself.
At the runtime you can use classpath.
And jax-ws library using resurce/META-INF/jax-ws-catalog.xml by default.
So I just duplicated this jax-ws-catalog.xml into next directories with different properties:
resource/jax-ws-catalog.xml
<?xml version="1.0"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" prefer="system">
<rewriteURI uriStartString="http://" rewritePrefix="local/"/>
<rewriteURI uriStartString="https://" rewritePrefix="local/"/>
</catalog>
resource/META-INF/jax-ws-catalog.xml
<?xml version="1.0"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" prefer="system">
<rewriteSystem systemIdStartString="http://www.w3.org/2006/03/addressing" rewritePrefix="classpath:local/www.w3.org/2006/03/addressing"/>
<rewriteSystem systemIdStartString="http://www.w3.org/2005/08/addressing" rewritePrefix="classpath:local/www.w3.org/2005/08/addressing"/>
</catalog>
In build.gradle I changed the next
tasks.withType(Wsdl2Java).configureEach {
toolOptions {
markGenerated.set(true)
outputDir.set(file("${buildDir}/generated"))
addToMainSourceSet.set(true)
wsdl.set(file("${projectDir}/src/main/resources/wsdl/myWsdl.wsdl"))
catalog.set("${projectDir}/src/main/resources/jax-ws-catalog.xml")
}
}

Gradle: how to declare a dependency to a specific configuration of a project programatically in java

Following the setup described in Simple sharing of artifacts between projects, we are in the special case where we have a multi module gradle build that produce different types of jars and we would like to declare a dependency to those jar in a configuration.
dependencies {
instrumentedClasspath(project(path: ":producer", configuration: 'instrumentedJars'))
}
from the docs works great.
In the project dependency-tests I have a project that reproduce the setup (with different names, but the idea is the same).
But I am doing this in a Gradle-plugin and I would like to have the same declaration in java.
DependencyHandler dependencyHandler = project.getDependencies();
// this adds a dependency to the main jar of the 'producer' project:
dependencyHandler.add("instrumentedClasspath", project.getRootProject().findProject(":producer"));
// this is not working:
dependencyHandler.add("instrumentedClasspath", project.getRootProject().findProject(":producer").getConfigurations().getByName("instrumentedJars"));
Failing with:
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':printConf'.
> Could not resolve all dependencies for configuration ':instrumentedJars'.
> Cannot convert the provided notation to an object of type Dependency: configuration ':producer:instrumentedJars' artifacts.
The following types/formats are supported:
- Instances of Dependency.
- String or CharSequence values, for example 'org.gradle:gradle-core:1.0'.
- Maps, for example [group: 'org.gradle', name: 'gradle-core', version: '1.0'].
- FileCollections, for example files('some.jar', 'someOther.jar').
- Projects, for example project(':some:project:path').
- ClassPathNotation, for example gradleApi().
Comprehensive documentation on dependency notations is available in DSL reference for DependencyHandler type.
* Try:
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
project(...)
inside the dependencies block comes from the DependencyHandler, and
path: ":producer", configuration: 'instrumentedJars'
is actually a map {"path"=":producer", "configuration"="instrumentedJars"}.
So something like that should work in Java:
Map<String, String> map = new HashMap<>();
map.put("path", ":producer");
map.put("configuration", "instrumentedJars");
dependencyHandler.add("instrumentedClasspath", dependencyHandler.project(map));
Note: When using Kotlin build script you can easily see types and declarations of functions and might be easier for discovering API. So in Kotlin project(...) in the dependencies block is an extension method defined as:
fun DependencyHandler.project(
path: String,
configuration: String? = null
): ProjectDependency =
uncheckedCast(
project(
if (configuration != null) mapOf("path" to path, "configuration" to configuration)
else mapOf("path" to path)
)
)

Cannot add task ':jacocoTestReport' as a task with that name already exists

I am trying to add the following task so that I can get some coverage data in my java + kotlin project (for what it is worth, this is a gradle project)... but I get the following error :
"Cannot add task ':jacocoTestReport' as a task with that name already exists"
Here is the actual task I am trying to add :
task jacocoTestReport(type: JacocoReport, dependsOn: "testDebugUnitTest") {
group = "Reporting"
description = "Generate Jacoco coverage reports for Debug build"
reports {
xml.enabled = true
html.enabled = true
}
// what to exclude from coverage report
// UI, "noise", generated classes, platform classes, etc.
def excludes = [
'**/R.class',
'**/R$*.class',
'**/*$ViewInjector*.*',
'**/BuildConfig.*',
'**/Manifest*.*',
'**/*Test*.*',
'android/**/*.*',
'**/*Fragment.*',
'**/*Activity.*'
]
// generated classes
classDirectories = fileTree(
dir: "$buildDir/intermediates/classes/debug",
excludes: excludes
) + fileTree(
dir: "$buildDir/tmp/kotlin-classes/debug",
excludes: excludes
)
// sources
sourceDirectories = files([
android.sourceSets.main.java.srcDirs,
"src/main/kotlin"
])
executionData = files("$buildDir/jacoco/testDebugUnitTest.exec")
}
Now, the issue I am confused about here, is that I can't find another class of this name anywhere... so perhaps there is something funky going on? I have tried googling this, but haven't really been able to find anything which truly helps me solve the problem.
All help greatly appreciated. I realize this is not a java or kotlin specific problem - but since it is a joint java + kotlin project, I thought I would tag both in this question, in case there is some nuanced issue that somebody else has seen.
Assuming you're already applying the Jacoco Gradle plugin, then yes, it already defines a task called jacocoTestReport, hence the error.
All you need to do is define your specific settings as per the documentation https://docs.gradle.org/current/userguide/jacoco_plugin.html#sec:jacoco_report_configuration
an example is below:
jacocoTestReport {
dependsOn "testDebugUnitTest"
reports {
xml.enabled = true
html.enabled = true
}
}
Most of the other configuration items you've listed belong in the 'jacoco' configuration block.
https://docs.gradle.org/current/userguide/jacoco_plugin.html#sec:jacoco_specific_task_configuration

Cannot cast generated Avro class to org.apache.avro.generic.IndexedRecord

I'm using commercehub-oss gradle plugin to generate Java classes by Avro protocol.
Here's my .avdl file:
#namespace("com.abc.xyz")
protocol XYZ_Protocol_v1 {
record VendorItemInfo {
string vendorItemId;
long price;
string deliveryChargeType;
}
record XyzDto {
array<VendorItemInfo> vendorItemInfos;
}
}
Based on commercehub-oss wiki, I ran $gradle build to generate the java files based on my .avdl file.
Then when I made a request to my service, I got this error stacktrace:
java.lang.ClassCastException: com.abc.xyz.domain.dto.VendorItemInfo cannot be cast to org.apache.avro.generic.IndexedRecord
org.apache.avro.generic.GenericData.getField(GenericData.java:666)
org.apache.avro.generic.GenericData.getField(GenericData.java:681)
org.apache.avro.generic.GenericDatumWriter.writeField(GenericDatumWriter.java:151)
org.apache.avro.specific.SpecificDatumWriter.writeField(SpecificDatumWriter.java:90)
org.apache.avro.generic.GenericDatumWriter.writeRecord(GenericDatumWriter.java:143)
org.apache.avro.generic.GenericDatumWriter.writeWithoutConversion(GenericDatumWriter.java:105)
org.apache.avro.generic.GenericDatumWriter.write(GenericDatumWriter.java:73)
org.apache.avro.generic.GenericDatumWriter.writeArray(GenericDatumWriter.java:179)
org.apache.avro.generic.GenericDatumWriter.writeWithoutConversion(GenericDatumWriter.java:107)
org.apache.avro.specific.SpecificDatumWriter.writeField(SpecificDatumWriter.java:87)
org.apache.avro.generic.GenericDatumWriter.writeRecord(GenericDatumWriter.java:143)
org.apache.avro.generic.GenericDatumWriter.writeWithoutConversion(GenericDatumWriter.java:105)
org.apache.avro.generic.GenericDatumWriter.write(GenericDatumWriter.java:73)
org.apache.avro.generic.GenericDatumWriter.write(GenericDatumWriter.java:60)
Any ideas how to fix this please?

Categories

Resources