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?
Related
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")
}
}
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!
In our project (java/spring/gradle stack), we are using openApi specs. We have a couple of services and specs for them. Also, we have common modules that duplicate in each spec. We moved those common modules to a separate spec file and include them in others. For instance:
specific_project1:
openapi:
spec.yaml
common_modules.yaml
build.gradle
The spec.yaml has the next code:
openapi: 3.0.0
info:
version: 0.0.1
paths:
/specific/post:
post:
requestBody:
context:
application/json:
schema:
$ref: "common_modules.yaml#/components/schemas/TestModule"
and the common_modules.yaml the next:
openapi: 3.0.0
info:
version: 0.0.1
components:
schemas:
TestModule:
type: object
properties:
value:
type: string
As the result, we need that spec.yaml to be generated with package name com.specific.project1, common_modules.yaml is generated with package name com.common.modules and the generated java class that is generated from spec.yaml has an import for TestModule with package com.common.modules in imports.
We found the solution on how to refer to the same object. We published TestModule as a separate project with its own package and in other projects, we used the importMappings configuration to define the proper package name for the object.
importMappings = [
TestModule: "com.common.modules.TestModule"
]
Yes it is possible
When you add openapi plug in to build.grade like
plugins {
id "org.openapi.generator" version "4.3.0"
}
You'll get access to openApiGenerate Task ,
This can be modified like this for example :
openApiGenerate {
generatorName = "jaxrs-jersey"
inputSpec = "$rootDir/spec-v1.yaml".toString()
outputDir = "$rootDir/".toString()
apiPackage = "name.of.api.package.rest.server.v1.api"
invokerPackage = "name.of.api.package.rest.server.v1.invoker"
modelPackage = "name.of.api.package.rest.server.v1.model"
configOptions = [
library: "jersey2"
]
}
here is the link for all the possible modification you can do related to spring for example https://github.com/OpenAPITools/openapi-generator/blob/master/docs/generators/spring.md
and for the full list of generators : https://github.com/OpenAPITools/openapi-generator/tree/master/docs/generators
In order to use 2 yaml files in a single prokect here is what you have to do .
task common(type: org.openapitools.generator.gradle.plugin.tasks.GenerateTask){
generatorName = "spring"
inputSpec = "$rootDir//schema/common.yaml".toString()
outputDir = "$rootDir/generated".toString()
apiPackage = "com.abc.code.generated.controller"
modelPackage = "com.abc.code.generated.model"
configOptions = [
dateLibrary: "java8"
]
systemProperties = [
invoker : "false",
generateSupportingFiles: "true"
]
additionalProperties = [
interfaceOnly : "true",
]
And you can leave the openApiGenerate for the spec.yaml
But make sure to add
compileJava.dependsOn common , tasks.openApiGenerate
So youll execute both of them .
Hope i helped .
I have an issue where Maven + frontend-maven-plugin and webpack doesn't go well together when I install an entire Maven module; Simply put Webpack the htmlwebpackPlugin will not inject the bundled js/css files the first time I install a Maven module, for some reason, even though a template is provided as such:
new HtmlWebpackPlugin({
template : '../resources/public/index.html',
filename : 'index.html',
inject : 'body',
})
However if I manually run the frontend-maven-plugin after installing the entire Maven module, it will actually inject the correct files, which is rather strange behavior.
To go around this, I wanted to know if there's a manual way to somehow inject these bundled files(I only have three; 1 css, 2 js files) with a chunkhash inside my own index.html template? That would make the build much more consistent.
A snip of my webpack.config.js - as you can see we add the chunkhash to the filenames if we are not in dev.
"use strict";
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const HtmlWebpackPlugin = require('html-webpack-plugin');
let path = require('path');
let webpack = require("webpack");
const PATHS = {
build: path.join(__dirname, '../../../target', 'classes', 'public'),
};
const env = process.env.NODE_ENV;
let isDev = false;
if(env == "dev"){
isDev = true;
}
console.log(`Dev environment: ${isDev}`);
module.exports = {
entry: {
main: './js/index.jsx',
vendor: [
"react","react-dom","axios",
"react-table", "mobx", "mobx-react", "mobx-utils", "lodash"],
},
output: {
path: PATHS.build,
filename: `bundle.${isDev ? '' : '[chunkhash]'}.js`
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({name: "vendor", filename: `/static/js/vendor.bundle.${isDev ? '' : '[chunkhash]'}.js`}),
new ExtractTextPlugin(`/static/css/[name].${isDev ? '' : '[chunkhash]'}.css`),
new HtmlWebpackPlugin({
template : '../resources/public/index.html',
filename : 'index.html',
inject : 'body',
})
],
module: {
loaders: [
// Bunch of loaders
]
},
};
I solved it - the issue was basically that Maven/Spring would take the Index.html(which I used as a template) in resources/public outside my target folder and overwrite it in the target folder - basically overwriting the output from webpackHTMLplugin, which makes logical sense in this context.
I solved it by not having any index.html file in resources/public, but just having a template.html in the src folder where webpack is. Thereby, it Maven/Spring doesn't overwrite the output with the empty template.
I'm using xjc in gradle as follows:
task xjc(type: JavaExec) {
inputs.files(schemaDir)
outputs.dir(generatedSrcDir)
main = 'com.sun.tools.xjc.Driver'
classpath = configurations.xjc
jvmArgs '-Djavax.xml.accessExternalSchema=all'
args '-quiet',
'-d',
"$generatedSrcDir",
'-classpath',
"$configurations.xjc.asPath",
'-disableXmlSecurity',
'-extension',
'-npa',
'-no-header',
'-enableIntrospection',
'-Xxew',
'-Xxew:instantiate lazy',
'-Xcomments',
'-Xcomments-mode=replace',
'-Xequals',
'-Xhashcode',
'-Xtostring',
"$schemaDir",
'-b',
"$schemaDir"
doFirst {
// Create directory for generated sources if not exists
mkdir(generatedSrcDir)
println "Generating JAXB sources with XJC version $jaxbVersion ..."
}
}
I need to know if I could mark with final all classes suitable?
P.S. Point of final here is to preserve the equals contract for generated classes.