Jooq 3.9.3 deletes custom generated java files after generate - java

This is an issue we face with migration from jooq version 3.4.1 to 3.9.3.
We have a setup in which we extend JavaGenerator and override generatePojo(TableDefinition tableDefinition) to create some custom enum from data in database. This enum is created in a bit hackish way, using PrintWriterand writing the data into FooEnum.java file.
Something like this:
public class FooGenerator extends JavaGenerator {
#Override
protected void generatePojo(TableDefinition table) {
super.generatePojo(table);
// this works in jooq 3.4.1 but not in 3.9.3
generateEnumClasses(table); // loads data and produces FooEnum.java with PrintWriter
}
}
What happens is that the FooEnum.java gets generated and then deleted shortly afterwards. Funny enough, if i create Foo.txt file in the directory where enum should be created, this file survives clean install.
It seems that the enum is deleted after first (of two) generate goals:
jooq-codegen-maven:3.9.3:generate
Any ideas why is the enum getting deleted and how to keep the behavior from version 3.4.1 where it survives ?
This custom generator that we use to extend JavaGenerator is supplied to plugin with:
<groupId>org.jooq</groupId>
<artifactId>jooq-codegen-maven</artifactId>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<id>some id</id>
<configuration>
<generator>
<name>org.jooq.util.FooGenerator</name>
// ...
</generator>
</configuration>
</execution>
</executions>

In case anybody else stumbles upon this, it seems that in newer jooq versions there is some cleanup code in
JavaGenerator {
public final void generate(Database db) {
// .... this deletes 'excess' java files
log.info("Removing excess files");
this.empty(this.getStrategy().getFileRoot(),this.scala?".scala":".java", this.files, this.directoriesNotForRemoval);
this.directoriesNotForRemoval.clear();
this.files.clear();
}
}
which deletes excess .java files.
Edit
Here is a link to github issue regarding this feature from Lukas comment.

Related

openapi generation - initialize objects

Iam using openapi-generator-maven-plugin for generating code from my yml files.
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<version>3.3.4</version>
When generating objects from the yml the generated code always generate objects and initilize them with null.
For example:
public class Foo {
#JsonProperty("bar")
private Bar bar = null;
}
Is there a way that the object is initialized with the object itself like:
public class Foo {
#JsonProperty("bar")
private Bar bar = new Bar();
}
Some snippets and links which can help You.
Plugin config in pom.xml:
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<version>4.2.2</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>${project.basedir}/docs/openapi/api.yml</inputSpec>
<generatorName>java</generatorName>
<templateDirectory>docs/openapi/template</templateDirectory>
</configuration>
</execution>
</executions>
</plugin>
Copy default templates e.g. from Java module of OpenAPI generator and put all mustache files inside some directory in Your project - check plugin configuration (in my case it is docs/openapi/template).
Find the file pojo.mustache which is a template to generate a POJO files.
You need to understand some basic Mustache syntax at this point. Find sych a fragment:
[...]
{{^isContainer}}
private {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}};
{{/isContainer}}
[...]
Change to whatever You want, e.g.:
[...]
{{^isContainer}}
private {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{^defaultValue}}{{^isPrimitiveType}} = new {{datatypeWithEnum}}(){{/isPrimitiveType}}{{/defaultValue}};
{{/isContainer}}
[...]
This template snippet will generate new TypeYouWantToUse() parts for every non primitive datatype.
Be aware that this is just a simple example how to proceed further. There are many corner cases e.g. enum handling.
FUrther readings:
OpenApi generator
OpenApi generator templating documentation

JOOQ 3.1 Code generate just for tables

Is it posible to run the code generator just for tables? I can exclude pkgs fine in <exclude> because they all end with _pkg but i am still generating functions and types as there is no common part in their name.
jOOQ 3.8 has added support for code generation flags to turn on/off specific types of generated artefacts (#3482). The configuration is:
<database>
<includePackages>false</includePackages>
<includeRoutines>false</includeRoutines>
...
Prior to version 3.8, you can still implement your own org.jooq.util.Database, e.g. overriding the OracleDatabase from jOOQ-meta, and then produce only TableDefinition items, none of the other items:
public class NoRoutinesOracleDatabase extends OracleDatabase {
#Override
protected List<RoutineDefinition> getRoutines0() {
return new ArrayList<>();
}
// other things you want to prevent...
}
You can then configure the code generator to use that Database:
<configuration>
<generator>
<database>
<name>com.example.NoRoutinesOracleDatabase</name>
...

Using a compile-time environment variable to configure RestApplicationPath

As stated in the documentation of rest-dispatch, the rest application path must be configured in the GIN module via a constant, here "/api/v1":
public class DispatchModule extends AbstractGinModule {
#Override
protected void configure() {
RestDispatchAsyncModule.Builder dispatchBuilder =
new RestDispatchAsyncModule.Builder();
install(dispatchBuilder.build());
bindConstant().annotatedWith(RestApplicationPath.class).to("/api/v1");
}
}
I would like to make the "/api/v1" constant be resolved at compile time, based on an environment variable set by the build system depending on the target environment (prod, dev, etc...), and on other criteria (the build artifact major version...).
The problem is I do not manage to rely on a compile time variable.
Neither TextResource/CssResource nor GWT's deferred binding won't help here, since GWT.create() cannot be used in GIN module. Another option I considered is using a custom Generator, but this seems to be too complex for this very simple need.
How do you solve this problem ?
If you use Maven as your build system, you could leverage the templating-maven-plugin to generate a Java class that will contain static variables defined in your POM file. That generated class will be used by your GWT code.
For example, you would want to populate a BuildConstants class template
public class BuildConstants {
// will be replaced by Maven
public static final String API_VERSION = "${myapi.version}";
}
and using a Maven property:
<myapi.version>v1</myapi.version>
that will be compiled to
public class BuildConstants {
// will be replaced by Maven
public static final String API_VERSION = "v1";
}
and you could reference those constants from within your DispatchModule:
bindConstant().annotatedWith(RestApplicationPath.class).to("/api/" + BuildConstants.API_VERSION);
Here's a sample config of the templating-maven-plugin that I use in a project:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>templating-maven-plugin</artifactId>
<version>1.0-alpha-3</version>
<executions>
<execution>
<id>filter-src</id>
<goals>
<goal>filter-sources</goal>
</goals>
<configuration>
<sourceDirectory>${basedir}/src/main/java-templates</sourceDirectory>
<outputDirectory>${project.build.directory}/generated-sources/java-templates
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
There's no reason you couldn't replace the bindConstant() with a #Provides method (or other bind().toProvider(), which would let you use a TextResource and/or deferred-binding, or whatever.
Asn an example (untested though), the code below uses JSNI to read the value from the host page, which makes it runtime dependent (rather than compile-time):
#Provides #RestApplicationPath native String provideRestApplicationPath() /*-{
return $wnd.restApplicationPath;
}-*/;
Following Thomas Broyer suggestion and Simon-Pierre, you could even bind different root .gwt.xml files depending on your maven profile. Then you choose the appropriate Gin module class where your constants are bound.
That is what we do inside the CarStore companion project of GWTP do do Form factors for example.

Version information for Java library, accessible at runtime

For supporting purposes I need to add a version and build identifier to our Java library. The library itself is a toolkit without user interaction which is used in different environments (stand alone Java applications, web applications, Eclipse applications, Maven dependency, ...).
What I want, is a class with some constants giving me the above described information (such as MyAppVersion.BUILD, ...), so that they can be shown e.g. in dialogs, command line output, etc. After my research, there seem to be the following approaches:
add versioning to file name, such as myLibrary-0.1.2.jar; not feasible in our case, since I have no control over the file name when deployed
add information to the MANIFEST.MF and read it programmatically, like described here. I'm not sure however, how robust this approach is in respect to different class loaders (Eclipse, OSGi, application servers, ...) and if the JAR file gets re-packaged, this information is lost
use a version.properties file holding the version, as described here and use a script during build to update the version.properties file
hard code the version information into the class directly and use a script to update this information
Are there any other approaches? The last option seems most "robust" to me, are there any objections against this variant? Is there a Maven plugin which would support updating this information in a MyAppVersion.java file during build?
I would suggest to use the templating-maven-plugin which is created exactly for such purposes.
You create at best a separate module which contains a template class like this (or within your module):
public final class Version {
private static final String VERSION = "${project.version}";
private static final String GROUPID = "${project.groupId}";
private static final String SVN = "${project.scm.developerConnection}";
private static final String SVN_BRANCH = "${scmBranch}";
private static final String REVISION = "${buildNumber}";
public static String getVersion() {
return VERSION;
}
public static String getGroupId() {
return GROUPID;
}
public static String getSVN() {
return SVN;
}
public static String getRevision() {
return REVISION;
}
public static String getSVNBranch() {
return SVN_BRANCH;
}
}
Which you simply put into src/main/java-templates folder plus an appropriate package name. Furthermore you configure the templating-maven-plugin like the following in your pom file:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>templating-maven-plugin</artifactId>
<version>1.0-alpha-3</version>
<executions>
<execution>
<goals>
<goal>filter-sources</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
This will generate a class Version which can be used by others and contains the given version. In the above template class you can use any property which is available in your build (things like JENKINS_ID etc.) or things your might define by yourself.
The result is that this class is compiled and packaged into your jar file.
Apart from that you can combine that with the buildnumber-maven-plugin to create the buildNumber which needs to be added to your pom file like this:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>buildnumber-maven-plugin</artifactId>
<version>1.2</version>
<configuration>
<revisionOnScmFailure>UNKNOWN</revisionOnScmFailure>
<getRevisionOnlyOnce>true</getRevisionOnlyOnce>
</configuration>
<executions>
<execution>
<goals>
<goal>create</goal>
</goals>
</execution>
</executions>
</plugin>
The last option of hardcoding the version is the most robust which seems to be important to you.
If you build using ant, you can write a class (let's call it VersionGenerator) that will generate a java file with version:
package my.cool.package;
public interface Version {
String VERSION = "1.2.3";
}
Call VersionGenerator from ant
And then compile all your code and roll it into a jar. And your jar will contain a freshly generated and compiled Version.class!
VersionGenerator will have the logic of how to name and increase versions

Run tests from a #Category using Maven

I have looked at a few other SO questions like this and this. But those questions are pretty dated and I'm curious if there exists a new solution.
Here's what my setup looks like:
Category interface:
public interface FastTest{}
Category suite:
#RunWith(Categories.class)
#IncludeCategory(FastTest.class)
public class FastSuite{}
Sample test:
#Category(FastTest.class)
public class FastTests{
#Test public void assertOneFastTest(){}
#Test public void assertTwoFastTest(){}
}
Using maven, let's say I want to only run all my FastTest tests. Ideally, I would use the command
mvn test -Dtest.category=FastTest
or
mvn test -Dtest.suite=FastSuite
But I have not been able to get this working. Does anyone have any suggestions aside from using ClasspathSuite? Thanks.
You can do this from the surefire plugin, using the configuration for groups, but you need to specify the junit47 provider as well. The following works for me:
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.11</version>
<dependencies>
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-junit47</artifactId>
<version>2.11</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>default-test</id>
<phase>test</phase>
<goals>
<goal>test</goal>
</goals>
</execution>
</executions>
<configuration>
<groups>com.xxx.foo.CategoryClass</groups>
</configuration>
</plugin>
I think this was introduced fairly recently, so may not work in earlier versions of the plugin, pre 2.11. You need to specify the provider, otherwise it doesn't work. The groups should be the fully qualified name of the Category class. You can also specify an excludeGroups as well if needs be.
For more information, see Maven Surefire Plugin surefire:test.
Did a little more research and found no options so I ended up using ClasspathSuite. It turns out that it's not any different except that you cannot specify #Category at a class level, you have to annotate every method you want to categorize
Now, each category suite looks like this:
#RunWith(Categories.class)
#Categories.IncludeCategory(FastTest.class)
#Suite.SuiteClasses(AllTests.class)
public class FastSuite{}
You have to modify AllTests to look like this:
#RunWith(ClasspathSuite.class)
public class AllTests{}
For methods, it looks like this:
public class FastTests{
#Categories(FastTest.class)
public void assertOneFastTest(){}
#Categories(FastTest.class)
public void assertTwoFastTest(){}
}
Using maven, you can do the following command:
mvn test -Dtest=FastSuite -Dt3-chrome-path=%CHROME_DRIVER_HOME -Dwebdriver.chrome.driver=%CHROME_DRIVER_HOME

Categories

Resources