JAXB Maven generate classes using multiple episodes - java

Using this maven plugin, I was able to generate my classes and reused them in another schema; which is really great!
Now I find myself with a schema needing two episodes (two different packages generated from schemas). I simply tried to add another arg in XJC, but it didn't work.
Then I changed the order of the two args, and the error targetted the other schema. I then understood that both episodes were OK, but it might not be the way of doing things.
Here is some of my pom:
<execution>
<id>business</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
..
<extension>true</extension>
<args>
<arg>-b</arg>
<arg>${project.basedir}/target/episodes/x.episode</arg>
<arg>${project.basedir}/target/episodes/y.episode</arg>
<arg>${project.basedir}/target/episodes/z.episode</arg>
</args>
..
</configuration>
</execution>
And here is what I get:
org.xml.sax.SAXParseException; systemId: file:/****.episode; lineNumber: 2; columnNumber: 65; s4s-elt-schema-ns: namespace element 'bindings' must be from 'http://ww.w3.org/2001.XMLSchema'.
From what I understand (after swapping their call in ), the three schemas/episodes are good, but I cannot use them both at the same time. Any way to do that?
Newbie here, any help much appreciated :).

Author of the maven-jaxb2-plugin here.
Why do you use args, why not just add your episodes in the configuration?
<episodes>
<episode>
<groupId>com.acme.foo</groupId>
<artifactId>package1</artifactId>
<!-- Version is not required if the artifact is
configured as dependency -->
</episode>
<episode>
<groupId>com.acme.foo</groupId>
<artifactId>package2</artifactId>
<!-- Version is not required if the artifact is
configured as dependency -->
</episode>
</episodes>
The whole idea of episodes is that you can point to the JAR (containing the episode file) and XJC will find out and use the binding from the contained episode. Using arg with -b is not what it was inteded for. :)
Concerning the error you're seeing, I guess the way you configure arg makes XJC think that your second and further episodes are actually schemas. I'd try to put intermediate -b arguments or configure all the episodes you refer to in one arg.
But I still think it is not the right way to use episodes. Compile your episodes as separate JARs/separate Maven modules, use them as dependencies and either configure them as episodes or just turn on the useDependenciesAsEpisodes option.

I have done this before on another project. I think you're using the wrong syntax:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>jaxb-Generic-XSD</id>
<phase>generate-sources</phase>
<goals>
<goal>xjc</goal>
</goals>
<configuration>
<enableIntrospection>false</enableIntrospection>
<schemaFiles>Generic.xsd</schemaFiles>
<schemaDirectory>${jaxb.schema.folder}</schemaDirectory>
<packageName>you.package.name.here</packageName>
<outputDirectory>${jaxb.output.folder}</outputDirectory>
<extension>true</extension>
<arguments>-b ${core.episode.file} -b ${containers.episode.file}</arguments>
</configuration>
</execution>
</executions>
</plugin>
Note the: <arguments>-b ${core.episode.file} -b ${containers.episode.file}</arguments> line.
I think you're using the same maven plugin, but if not, then take note of the plugin version groupId, artifactId, and use it instead.

Related

How can I specify java interfaces file names using openapi.yaml and swagger-codegen-maven-plugin

I'm trying to generate 2 controller classes for 2 scopes in my project.
I can do that with 2 separate openapi.yaml files, and 2 maven executions.
I'm using swagger-codegen-maven-plugin to get it done, and I could only find code that uses swagger.yaml or openapi.yaml with a different plugin.
I can't find this combination, though I'm positive it's possible.
The question is if I have 2 scopes such as 'DB' and 'Browse', and I want to have 2 interfaces created for the 2 scopes such as DBApi.java and BrowseApi.java, how can it be done, and if it can be done using 1 openapi.yaml file?
I did see example projects where 1 openapi.yaml file resulted in PetApi.java and StoreApi.java, but I couldn't find how to configure this in my setup.
Thanks.
The relevant part in the maven pom file is:
<groupId>io.swagger.codegen.v3</groupId>
<artifactId>swagger-codegen-maven-plugin</artifactId>
<executions>
<execution>
<id>raptor-codegen</id>
<configuration>
<apiPackage>com.app.seo.graph.rest.v1.api</apiPackage>
<modelPackage>com.app.seo.graph.rest.v1.model</modelPackage>
<inputSpec>${project.basedir}/src/main/resources/api/openapi.yaml</inputSpec>
<configOptions>
<dateLibrary>java8</dateLibrary>
<additional-properties>preAuthorize=hasAuthority,useJsonPropertyOrder=true,resourceMetaType=com.ebay.jaxrs.server.ResourceOperation</additional-properties>
</configOptions>
</configuration>
</execution>
</executions>
</plugin>
I've used <useTags>true</useTags> under <configOptions> in my Maven file and it works for me. YAML definition
paths:
'/operation/':
get:
tags:
- Some-Service
generates "SomeServiceApi" class name with the SpringCodegen generator. Using "openapi-generator-maven-plugin" in the "6.2.0" version.

Is it possible to configure maven to compile generated sources wouthout the use of a plugin?

I know this question is not new. But it seems that there is no definite answer. This answer from 2012 states that if generated sources are placed under target/generated-sources/<tool> they will be compiled. ANTLR 4 maven plugin follows this paradigm. Per documentation, the default value of outputDirectory is: ${project.build.directory}/generated-sources/antlr4.
Now in my case I have a custom tool that generates sources. I've set its output directory to be at ${project.build.directory}/generated-sources/whatever and it didn't work. Regarding the whateverpart, I've tried to use the id of the goal that generates the sources and even tried to hijack antlr4 name. No result though.
When I try this solution that suggests using mojo build-helper-maven-plugin it compiles as expected. But according to maven guide to generating sources it should be working without any helper plugin, shouldn't it? Am I missing something?
Here is the POM (fragment) configuration that I use to generate the sources.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.4.0</version>
<executions>
<execution>
<id>generate-code</id>
<phase>generate-sources</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<includeProjectDependencies>false</includeProjectDependencies>
<includePluginDependencies>true</includePluginDependencies>
<executableDependency>
<groupId>com.company.product</groupId>
<artifactId>CodeGenerator</artifactId>
</executableDependency>
<arguments>
<argument>${basedir}/</argument>
<argument>${project.build.directory}/generated-sources/generate-code/</argument>
</arguments>
<mainClass>com.company.codegeneration.CodeGenerator</mainClass>
</configuration>
<dependencies>
<dependency>
<groupId>com.company.product</groupId>
<artifactId>CodeGenerator</artifactId>
<version>1.0-SNAPSHOT</version>
<type>jar</type>
</dependency>
</dependencies>
</plugin>
Your understanding is just a bit incorrect.
Nothing automatic, plugins generating source code typically handle that by adding their output directory (something like target/generated-sources/ by convention) as source directory to the POM so that it will be included later during the compile phase.
Some less well implemented plugins don't do that for you and you have
to add the directory yourself, for example using the Build Helper
Maven Plugin.
As the other answer noted, most plugins typically add the generated code as new source path.
Ex: See antlr4's Antlr4Mojo.java class. Here, the plugin is adding the generated classes to project source by calling addSourceRoot method in execute method.
// Omitted some code
void addSourceRoot(File outputDir) {
if (generateTestSources) {
project.addTestCompileSourceRoot(outputDir.getPath());
}
else {
project.addCompileSourceRoot(outputDir.getPath());
}
}
// Omitted some code
#Override
public void execute() throws MojoExecutionException, MojoFailureException {
// Omitted code
if(project!=null)
{
// Tell Maven that there are some new source files underneath the output
// directory.
addSourceRoot(this.getOutputDirectory());
}
}
// Omitted some code
So, you can either do this in your custom plugin or use the build-helper-maven-plugin.

Maven resource plugin doesn't filter out customized delimiters nested in ${}

I have a properties file:
property.a=$[value]
I am using maven-resources-plugin with filtering on this property file enabled in order to substitute build variables in there:
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<delimiters>
<delimiter>$[*]</delimiter>
</delimiters>
</configuration>
</plugin>
Everything works flawlessly, until $[*] token is not nested into ${*} one, like below:
property.a=${VALUE:$[value]}
Assuming value=XXX in Maven properties, I expected to get:
property.a=${VALUE:XXX}
However, Maven resources plugin doesn't substitute $[value] in there, leaving filtered contecnts as-is. I tried enabling supportMultiLineFiltering but it changed nothing. It feels like despite <delimiters> option is set explicitly, plugin treats ${*} as a valid delimiter either, and tries to filter it, without success.
How should I configure maven resources plugin so that it filters the property file contents as expected?
I just realized I missed a configuration option in maven resource plugin, designed specially for controlling default delimiters - useDefaultDelimiters, which is true by default. The configuration below solved the issue:
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<delimiters>
<delimiter>$[*]</delimiter>
</delimiters>
<useDefaultDelimiters>false</useDefaultDelimiters>
</configuration>
</plugin>

How to share/pass a variable with application properties and pom file

I have a multi module spring-boot project, before integration tests of my app, I start another child module (which is Stub made by another spring boot app) You can see it is attached to "pre-integration-test" and it is working fine finally.
Parent Pom
|
|----myRealApp module(spring boot app)
|----stub module(This is also a spring-boot app)
My question is, is there a way to randomize And share this port (not fixed to 8090), so concurrent builds on Jenkins server can run tests and not fail because address is in use already.
I know I can generate random numbers/ports in spring properties file. But couldn't find a way to pass it to Pom.
application-test.properties of myRealApp:
stub.port=8090
stub.url=http://localhost:${stub.port}/stub/api/v1/domains/
Pom of myRealApp:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>${spring.boot.mainclass}</mainClass>
</configuration>
<executions>
<execution>
<id>start-stub</id>
<configuration>
<arguments>
<argument>--server.port=8090</argument>
</arguments>
<mainClass>io.swagger.Stub</mainClass>
<classesDirectory>../my-stub/target/classes</classesDirectory>
</configuration>
<goals>
<goal>start</goal>
</goals>
<phase>pre-integration-test</phase>
</execution>
<execution>
<goals>
<goal>build-info</goal>
</goals>
</execution>
</executions>
</plugin>
You can do that via jenkins Port Allocator Plugin
Once you assign the port (lets say HTTP_PORT), then you can pass this as command line
-Dstub.port=$HTTP_PORT
I recommend you not to randomize at all. My suggestion is to parametrize the server port in the POM and application-test.properties files, and set a value based upon some Jenkins-provided variable: For example, BUILD_NUMBER, which is incremented on every build and thus uniqueness is guranteed.
However, there is a problem about this: You also need to enclose the port number within valid boundaries: TCP ports must be within 1024 and 65535, however BUILD_NUMBER is not limited at all.
How to cope with this? I think a simple Ant task bound to the initialize phase could read the BUILD_NUMBER value, apply it a simple formula 1024+(BUILD_NUMBER % 64512), and set it as the definitive port number variable, which is the one you will reference in the POM and application-test.properties files.

Java 9: How to find every new method added

With the release of Java 9, numerous methods have been added to many classes, most (if not all) of which contain the following in their documentation:
Since: 9
Is there an easy way to find any new methods added in an arbitrary class without having to scour through its documentation?
Example: ByteBuffer.alignedSlice
You're probably looking for something like jdkapidiff which uses japicmp to generate reports similar to one hosted here by the author - jdk8-jdk9-api-diff.
You can clone the project and execute mvn clean install to get the similar report on your local.
Provide a file ~.m2/toolchains.xml like this:
<?xml version="1.0" encoding="UTF8"?>
<toolchains>
<toolchain>
<type>jdk</type>
<provides>
<version>1.8</version>
<vendor>oracle</vendor>
</provides>
<configuration>
<jdkHome>/path/to/jdk-1.8</jdkHome>
</configuration>
</toolchain>
<toolchain>
<type>jdk</type>
<provides>
<version>9</version>
<vendor>oracle</vendor>
</provides>
<configuration>
<jdkHome>/path/to/jdk-9</jdkHome>
</configuration>
</toolchain>
</toolchains>
There are many changes to existing classes and members, in addition to new #since 9 classes and members. The final release of JSR 379 include an annex with the complete set of diffs. The draft is online here:
http://cr.openjdk.java.net/~iris/se/9/java-se-9-fr-spec-01/apidiffs/overview-summary.html

Categories

Resources