jOOQ codegen strategy class not found - java

I'm trying to add a -Pojo suffix to my generated jOOQ pojos.
The strategy implementation is straightforward enough:
package my.app.jooq.strategy
import org.jooq.codegen.DefaultGeneratorStrategy
import org.jooq.codegen.GeneratorStrategy
import org.jooq.codegen.GeneratorStrategy.Mode.POJO
import org.jooq.meta.Definition
class MyGeneratorStrategy : DefaultGeneratorStrategy() {
override fun getJavaClassName(definition: Definition, mode: GeneratorStrategy.Mode): String {
return when (mode) {
POJO -> super.getJavaClassName(definition, mode) + "Pojo"
else -> super.getJavaClassName(definition, mode)
}
}
}
but codegen just refuses to pick it up. (ClassNotFoundException).
According to https://groups.google.com/g/jooq-user/c/LM5ioRHNhJw :
you would have to create a separate project/module only for that strategy class, in order to create a dependency graph like so:
Code generation module... depends on
Strategy module... depends on
jOOQ libraries
so I did... jOOQ doesn't care.
PM org.jooq.tools.JooqLogger error
SEVERE: Error in file: /home/user/code/my-app/backend/db/build/tmp/generateMyAppJooq/config.xml. Error : my.app.jooq.strategy.MyGeneratorStrategy
java.lang.ClassNotFoundException: my.app.jooq.strategy.MyGeneratorStrategy
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
at org.jooq.codegen.GenerationTool.loadClass0(GenerationTool.java:1075)
at org.jooq.codegen.GenerationTool.loadClass(GenerationTool.java:1005)
at org.jooq.codegen.GenerationTool.run0(GenerationTool.java:405)
at org.jooq.codegen.GenerationTool.run(GenerationTool.java:233)
at org.jooq.codegen.GenerationTool.generate(GenerationTool.java:228)
at org.jooq.codegen.GenerationTool.main(GenerationTool.java:200)
here's how the codegen module is set up:
plugins {
id 'nu.studer.jooq' version "${plugin_jooq}"
id 'io.spring.dependency-management'
}
dependencyManagement {
imports {
mavenBom SpringBootPlugin.BOM_COORDINATES
mavenBom "org.jetbrains.kotlin:kotlin-bom:${fw_kotlin}"
}
}
dependencies {
api "org.postgresql:postgresql"
implementation project(":backend-jooq-config")
api "org.springframework.boot:spring-boot-starter-jooq"
implementation "org.jooq:jooq-meta"
implementation "org.jooq:jooq-codegen"
jooqGenerator "org.postgresql:postgresql"
}
jooq {
version = dependencyManagement.importedProperties['jooq.version']
edition = nu.studer.gradle.jooq.JooqEdition.OSS
configurations {
myApp {
generateSchemaSourceOnCompilation = true
generationTool {
logging = org.jooq.meta.jaxb.Logging.WARN
jdbc {
driver = 'org.postgresql.Driver'
url = 'jdbc:postgresql://localhost:5432/myapp'
user = 'user'
password = 'password'
properties {
property {
key = 'PAGE_SIZE'
value = 2048
}
}
}
generator {
name = 'org.jooq.codegen.DefaultGenerator'
strategy {
name = 'my.app.jooq.strategy.MyGeneratorStrategy'
}
database {
name = 'org.jooq.meta.postgres.PostgresDatabase'
inputSchema = 'public'
includes = '.*'
excludes = ''
}
generate {
daos = true
springAnnotations = true
}
target {
directory = 'src/main/java'
packageName = 'my.app.db'
}
}
}
}
}
}
I don't see what I'm doing wrong.
And yes, the strategy is being compiled:
find .. -name "*GeneratorStrategy*"
../backend/jooq-config/build/classes/kotlin/main/my/app/jooq/strategy/MyGeneratorStrategy.class
../backend/jooq-config/build/classes/kotlin/main/my/app/jooq/strategy/MyGeneratorStrategy$WhenMappings.class
../backend/jooq-config/src/main/kotlin/my/app/jooq/strategy/MyGeneratorStrategy.kt
how do I resolve this?

Fixing your configuration
There's an example here on how to set up this third party code generation plugin to use a custom strategy:
https://github.com/etiennestuder/gradle-jooq-plugin/tree/master/example/configure_custom_generator_strategy
As you can see, the dependency is specified as:
jooqGenerator project(':backend-jooq-config')
Not
implementation project(':backend-jooq-config')
Using a declarative configuration instead
For such simple cases, jOOQ also offers an out-of-the-box configuration called "matcher strategy," where it matches names and replaces them by something else. E.g.
generator {
strategy {
matchers {
tables {
table {
pojoClass {
transform = 'PASCAL'
expression = '\$0_POJO'
}
}
}
}
}
}

Related

Migration from Flyway 4 to 8 SqlMigrationResolver

I am beginner programmer. I am working in project with flyway-core 4.0.3 and I am migrating it to flyway 8.0.5. One thing is left and I don't know how to migrate this. I am pasting a class - this is a class that filters sql scripts. Apart from standard locations parameter we have also filtering mechanism based on some file name conditions (not prefix and not suffix). I am using free version of flyway, that's why I cannot use some features like placeholders.
This is a piece of code that filters scripts choosing only those that has DDL in name, just an example for business filter. There would be other things to filter in file name also..
try (Connection connectionMetaDataTable = JdbcUtils.openConnection(dataSource)) {
DbSupport dbSupport = DbSupportFactory.createDbSupport(connectionMetaDataTable, true);
String scriptsLocation = prepareLocation();
Flyway flyway = new Flyway();
flyway.setDataSource(dataSource);
flyway.setLocations(scriptsLocation);
flyway.setEncoding("UTF-8");
CustomMigrationResolver customMigrationResolver = new CustomMigrationResolver (
flyway,
dbSupport,
new Scanner(Thread.currentThread().getContextClassLoader()),
new Location(scriptsLocation));
flyway.setResolvers(customMigrationResolver );
flyway.setSkipDefaultResolvers(true);
flyway.migrate();
} catch (SQLException e) {
LOGGER.error(e.getMessage(), e);
}
public class CustomMigrationResolver extends SqlMigrationResolver {
public CustomMigrationResolver(Flyway flyway, DbSupport dbSupport, Scanner scanner, Location location) {
super(dbSupport, scanner, location, PlaceholderReplacer.NO_PLACEHOLDERS, flyway.getEncoding(), flyway.getSqlMigrationPrefix(), flyway.getRepeatableSqlMigrationPrefix(),
flyway.getSqlMigrationSeparator(), flyway.getSqlMigrationSuffix());
}
#Override
public List<ResolvedMigration> resolveMigrations() {
List<ResolvedMigration> allMigrations = super.resolveMigrations();
List<ResolvedMigration> onlyDdlMigrations = allMigrations.stream().filter(m -> m.getDescription().startsWith("DDL")).collect(Collectors.toList()); //some shortened business filtering condiitons
return onlyDdlMigrations;
}
In flyway 8.0.4 my customMigrationResolver could look like this:
public class Flyway8CustomMigrationResolver extends SqlMigrationResolver {
public Flyway8CustomMigrationResolver(ResourceProvider resourceProvider,
SqlScriptExecutorFactory sqlScriptExecutorFactory,
SqlScriptFactory sqlScriptFactory,
Configuration configuration,
ParsingContext parsingContext) {
super(resourceProvider, sqlScriptExecutorFactory, sqlScriptFactory, configuration, parsingContext);
}
#Override
public List<ResolvedMigration> resolveMigrations(Context context) {
List<ResolvedMigration> allMigrations = super.resolveMigrations(context);
//some business filtering of the files..
return onlyDdlMigrations;
}
}
There are no examples how to provide all parameters for Flyway8CustomMigrationResolver constructor, can you help me?

Artifactory + Custom Gradle Plugin Programmatically (2022)

I'm trying to create a custom gradle plugin (100% java) which will automatically configure Artifactory, avoiding the need of the following DSL:
artifactory {
contextUrl = "${artifactory_contextUrl}" //The base Artifactory URL if not overridden by the publisher/resolver
publish {
repository {
contextUrl = "${artifactory_contextUrl}"
repoKey = 'android-dev'
username = "${artifactory_user}"
password = "${artifactory_password}"
maven = true
}
}
resolve {
repository {
contextUrl = "${artifactory_contextUrl}"
repoKey = 'android-dev-distributions'
username = "${artifactory_user}"
password = "${artifactory_password}"
maven = true
}
}
}
I'm trying to re-create #agrosner own solution (from https://stackoverflow.com/a/25669431/1880280) but I'm missing "ArtifactoryAction". I can't find it anywhere.
The nonworking version posted by #agrosner is the following code:
// Set up plugins so we never need to add them to a build.gradle
project.getPlugins().apply(MAVEN);
project.getPlugins().apply(ARTIFACTORY);
project.setGroup(GROUP);
// Add Artifactory repo to the repositories
project.getRepositories().maven(new ArtifactoryAction(contextUrl + ARTIFACTORY_REPO_ENDPOINT, user, pass));
// We will define the plugin convention here so all of our libraries do not need to
// declare the artifactory closure manually
ArtifactoryPluginConvention pluginConvention =
ArtifactoryPluginUtil.getArtifactoryConvention(project);
pluginConvention.setContextUrl(contextUrl);
PublisherConfig publisherConfig = new PublisherConfig(pluginConvention);
publisherConfig.setContextUrl(contextUrl);
pluginConvention.setPublisherConfig(publisherConfig);
// Use reflection to access private field
PublisherConfig.Repository repository = null;
Field[] fields = PublisherConfig.class.getDeclaredFields();
for(Field field : fields) {
if(field.getName().equalsIgnoreCase("repository")) {
try {
field.setAccessible(true);
repository = (PublisherConfig.Repository) field.get(publisherConfig);
} catch (Exception e) {
e.printStackTrace();
}
}
}
if(repository != null) {
repository.setPassword(pass);
repository.setUsername(user);
repository.setRepoKey(PUBLISHER_REPO_KEY);
repository.setMavenCompatible(true);
}
GradleArtifactoryClientConfigUpdater.update(pluginConvention.getClientConfig(), project.getRootProject());
Can anyone help with an updated 100% java version of this?
Additionally, how would be for the following DSL?
artifactory {
publish {
repository {
repoKey = 'default-gradle-dev-local' // The Artifactory repository key to publish to
username = "${artifactory_user}" // The publisher user name
password = "${artifactory_password}" // The publisher password
maven = true
}
defaults {
publications('mavenJava')
publishArtifacts = true
publishPom = true
}
}}
Thanks in advance
César
ps. The DSL version that was published at #agrosner question thread is not useful for me. I need a Java version.
For your first question related to ArtifactoryAction: this is neither Gradle API nor Artifactory plugin related api, but most probably a custom class that the response author has implemented himself, as a shortcut to declare his custom Artifactory maven repo.
See this API, used to declare maven repositories :
MavenArtifactRepository maven​(Action<? super MavenArtifactRepository> action)
So you can use:
project.getRepositories().maven( mavenArtifactRepository -> {
mavenArtifactRepository.setUrl(contextUrl + MAVEN_PUBLIC_REPO);
mavenArtifactRepository.getCredentials().setUsername("user");
mavenArtifactRepository.getCredentials().setPassword("password");
});
or wrap the action code into a custom implementation of Action<? super MavenArtifactRepository> :
project.getRepositories().maven( new ArtifactoryAction(contextUrl + MAVEN_PUBLIC_REPO, "user", "password") );
[...]
// custom action class, defined somewhere else
class ArtifactoryAction implements Action<MavenArtifactRepository> {
private final String url, userName, password;
ArtifactoryAction(String url, String userName, String password) {
this.url = url; this.userName = userName; this.password = password;
}
#Override
public void execute(MavenArtifactRepository target) {
target.setUrl(url);
target.getCredentials().setUsername(userName);
target.getCredentials().setPassword(password);
}
}
For the other question with java translation of the artifactory { } DSL : see full example below with some inline comments. ( not tested but translated from my kotlin implementation which works fine)
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.publish.maven.plugins.MavenPublishPlugin;
import org.jfrog.gradle.plugin.artifactory.ArtifactoryPlugin;
import org.jfrog.gradle.plugin.artifactory.ArtifactoryPluginUtil;
import org.jfrog.gradle.plugin.artifactory.dsl.ArtifactoryPluginConvention;
import org.jfrog.gradle.plugin.artifactory.dsl.PublisherConfig;
public class CustomArtifactoryPlugin implements Plugin<Project> {
private static String MAVEN_PUBLIC_REPO = "/maven-public";
private String contextUrl = "MY_CUSTOM_REPO_BASE_URL";
#Override
public void apply(Project project) {
// Base gradle publishing plugin
// - maven plugin for pulishing java artefacts
// - ivy plugin if for publishing other type of artefacts: rpms, archives, ..
project.getPluginManager().apply(MavenPublishPlugin.class);
// project.getPluginManager().apply(IvyPublishPlugin.class);
// Apply the Artifactory plugin
project.getPluginManager().apply(ArtifactoryPlugin.class);
// Add Artifactory repo to the repositories
project.getRepositories().maven(new ArtifactoryAction(contextUrl + MAVEN_PUBLIC_REPO, "user", "password"));
// Configure artifactory plugin - using 'withPlugin' ensures that plugin has already been applied
project.getPluginManager().withPlugin("com.jfrog.artifactory", appliedPlugin -> {
// artifactory {
ArtifactoryPluginConvention pluginConvention = ArtifactoryPluginUtil.getArtifactoryConvention(project);
// contextUrl = "${contextUrl}"
pluginConvention.setContextUrl(contextUrl);
// publish {
PublisherConfig publisherConfig = new PublisherConfig(pluginConvention);
pluginConvention.setPublisherConfig(publisherConfig);
// repository {
pluginConvention.getPublisherConfig().repository(repository -> {
// repoKey = 'default-gradle-dev-local' ...
repository.setRepoKey("default-gradle-dev-local"); // The Artifactory repository key to publish to
repository.setUsername("${artifactory_user}"); // The publisher user name
repository.setPassword("${artifactory_password}"); // The publisher password
repository.setMavenCompatible(true);
});
// defaults {
pluginConvention.getPublisherConfig().defaults(artifactoryTask -> {
// publications('mavenJava')
artifactoryTask.publications("mavenJava");
artifactoryTask.setPublishArtifacts("true");
artifactoryTask.setPublishPom("true");
});
});
}
}
EDIT for the publication configuration, you can do as follows:
// create maven publication
project.getExtensions().configure(PublishingExtension.class, publishingExtension -> {
publishingExtension.publications(publications -> {
publications.create("mavenPublication", MavenPublication.class, mavenPublication -> {
mavenPublication.setVersion("1.0.0");
mavenPublication.setGroupId("groupId");
mavenPublication.from(project.getComponents().findByName("java"));
});
});
});

Publish java library with custom primary artifact

I m trying to create a java library with custom primary artifact..
I followed this documentation, but the problem is when i run the "publish" task, i get this error.
Could not determine the dependencies of task ':publishMavenPublicationToMyRepoRepository'.
> Task with path 'rpm' not found in root project 'commons'.
This is my gradle file :
import com.netflix.gradle.plugins.rpm.Rpm
plugins {
`java-library`
`maven-publish`
id("nebula.ospackage") version "7.4.1"
kotlin("jvm") version "1.3.50"
}
group = "com.test"
version = "1.0.0"
java.sourceCompatibility = JavaVersion.VERSION_1_8
repositories {
mavenCentral()
}
dependencies {
implementation("javax.xml.bind:jaxb-api:2.3.1")
implementation("io.jsonwebtoken:jjwt:0.9.1")
implementation("com.googlecode.libphonenumber:libphonenumber:8.10.14")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.9.9")
}
tasks.withType<Rpm> {
version = "1.0.0"
release = "1"
packageName = "com.test.commons"
into("$buildDir/rpms/com.test.commons.rpm")
}
val rpmFile = file("$buildDir/rpms/com.test.commons.rpm")
val rpmArtifact = artifacts.add("archives", rpmFile) {
type = "rpm"
builtBy("rpm")
}
publishing {
publications {
create<MavenPublication>("maven") {
artifact(rpmArtifact)
}
}
repositories {
maven {
name = "myRepo"
url = uri("file://${buildDir}/repo")
}
}
}
I think the problem is in the rpm task, how can i solve that?
The rpm task type is available with the nebula.rpm plugin as explained in the wiki here
plugins {
id("nebula.ospackage") version "7.4.1"
id("nebula.rpm") version "7.4.1"
}
Not familiar with this plugin, but it doesn't look like applying nebula.ospackage is enough.
The nebula.ospackage plugin will create a task named buildRpm of type com.netflix.gradle.plugins.rpm.Rpm.
In your script you reference a task by the name rpm, which does not exists : this explains the error you got (> Task with path 'rpm' not found in root project 'commons'.)
Just update your script to use correct task name :
val rpmArtifact = artifacts.add("archives", rpmFile) {
type = "rpm"
builtBy("buildRpm") // <=== instead of "rpm"
}
Note : you don't have to apply plugin nebula.rpm, nebula.ospackage is enough.

How to conditionally apply source set excludes to build based on parameter provided

I'm using Gradle 4.4 (edit: issue still present in Gradle 4.8). For reasons my project has the following layout
src/main/java/com/company/common
src/main/java/com/company/mod1
src/main/java/com/company/mod2
The build can generate either mod1 or mod2, depending on the build task executed. Classes from mod1 shall never use classes from mod2 and vice versa. Therefore I want the build to fail, if either uses classes from the other. However I still want to be able to develop both sources in Eclipse, which is why I only want the build to fail on our CI server. The CI server provides a parameter CI_BUILD. The build file uses the following mechanism to allow this:
Excludes aren't applied properly here:
ext {
ext_template_mod1 = [:]
ext_template_mod1.src_excludes = "**/mod2/**"
ext_template_mod2 = [:]
ext_template_mod2.src_excludes = "**/mod1/**"
if (project.hasProperty("mod2")) {
ext_template = ext_template_mod2
} else {
ext_template = ext_template_mod1
}
}
sourceSets {
main {
java {
if (project.hasProperty("CI_BUILD")) {
exclude "${project.ext_template.src_excludes}"
}
}
}
}
For some reason this doesn't work. gradlew build -PCI_BUILD doesn't fail if a source file on mod1 references a source file from mod2.
I fail to understand why it doesn't. If I don't check for the project property, the exclude works as expected:
Working configuration:
ext {
ext_template_mod1 = [:]
ext_template_mod1.src_excludes = "**/mod2/**"
ext_template_mod2 = [:]
ext_template_mod2.src_excludes = "**/mod1/**"
if (project.hasProperty("mod2")) {
ext_template = ext_template_mod2
} else {
ext_template = ext_template_mod1
}
}
sourceSets {
main {
java {
exclude "${project.ext_template.src_excludes}"
}
}
}
Now gradlew build -PCI_BUILD fails as expected when a source file on mod1 references a source file from mod2.
But now my IDE won't recognize the sources in the mod2 folder as sources anymore.
How can I apply excludes to my source set based on the existence of a build parameter?
I've been creating a minimal example and it works just fine there:
apply plugin: 'java'
ext {
ext_template_mod1 = [:]
ext_template_mod1.src_excludes = "**/mod2/**"
ext_template_mod2 = [:]
ext_template_mod2.src_excludes = "**/mod1/**"
if (project.hasProperty("mod2")) {
ext_template = ext_template_mod2
} else {
ext_template = ext_template_mod1
}
}
sourceSets {
main {
java {
if (project.hasProperty("CI_BUILD")) {
exclude "${project.ext_template.src_excludes}"
}
}
}
}
jar {
if (project.hasProperty("CI_BUILD")) {
exclude "${project.ext_template.src_excludes}"
}
}
The issue above was an artifact of my own build. I had used dynamic task generation and forgotten to provide the parameter I was checking for as a startParameter.projectProperties.

webapp doesnt start after spring-boot update to 1.3.1

I hope you can help me with this problem and couldn't find a solution.
I am working on a Webapplication with gradle 2.4, Java 8, Spring-boot and a H2-DB. We started with Spring-Boot 1.2.2 a while ago and decided to update Spring-Boot to 1.3.1. But with this Version the Server doesnt start anymore. It throws a NullPointerException when I start the Project (gradle bootRun)
2016-01-14 17:39:22.472 ERROR 8304 --- [ main] o.s.boot.SpringApplication : Application startup failed
java.lang.NullPointerException: null
at org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer.onApplicationEvent(DataSourceInitializer.java:100) ~[spring-boot-autoconfigure-1.3.1.RELEASE.jar:1.3.1.RELEASE]
at org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer.onApplicationEvent(DataSourceInitializer.java:47) ~[spring-boot-autoconfigure-1.3.1.RELEASE.jar:1.3.1.RELEASE]
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:163) ~[spring-context-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:136) ~[spring-context-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:119) ~[spring-context-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.registerListeners(AbstractApplicationContext.java:809) ~[spring-context-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:535) ~[spring-context-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118) ~[spring-boot-1.3.1.RELEASE.jar:1.3.1.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:764) ~[spring-boot-1.3.1.RELEASE.jar:1.3.1.RELEASE]
at org.springframework.boot.SpringApplication.doRun(SpringApplication.java:357) ~[spring-boot-1.3.1.RELEASE.jar:1.3.1.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:305) ~[spring-boot-1.3.1.RELEASE.jar:1.3.1.RELEASE]
at com.infinit.organization.config.Application.main(Application.java:46) [main/:na]
The build.gradle:
buildscript {
// The buildscript closure is executed at the beginning of gradle's configuration phase.
// It defines dependencies on gradle plugins that are used in the remaining configuration phase
// and in the execution phase.
// Note that spring-boot registers a custom Gradle ResolutionStrategy that allows to omit version numbers
// when declaring dependencies. Only the plugin version must be set.
ext {
springBootVersion = '1.3.1.RELEASE'
}
// repositories used to resolve gradle plugins
repositories {
maven { url "http://download.osgeo.org/webdav/geotools/"}
mavenCentral()
maven { url "http://repo.spring.io/libs-snapshot" }
maven { url "http://dl.bintray.com/infinit/infinit-opensource" }
maven { url "http://dl.bintray.com/letteral/opensource" }
maven { url 'https://repo.gradle.org/gradle/plugins-releases'}
}
// dependent gradle plugins
dependencies {
classpath "org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}"
classpath "net.saliman:gradle-cobertura-plugin:2.3.0"
classpath "com.letteral:letteral-gradle-plugin:0.0.5"
}
}
// repositories used for satisfying project's configuration dependencies (e.g. compile, runtime)
repositories {
maven { url "http://download.osgeo.org/webdav/geotools/"}
mavenCentral()
maven { url "http://repo.spring.io/libs-snapshot" }
maven { url "https://oss.sonatype.org/content/repositories/snapshots" } // cobertura snapshots
maven { url "http://dl.bintray.com/infinit/infinit-opensource" }
maven { url "http://dl.bintray.com/letteral/opensource" }
maven { url 'https://repo.gradle.org/gradle/plugins-releases'}
}
// plugins needed in the build process
apply plugin: 'java'
apply plugin: 'groovy'
apply plugin: 'war'
apply plugin: 'net.saliman.cobertura'
apply plugin: 'spring-boot'
apply plugin: 'letteral'
apply from: 'gensrc.gradle'
apply from: 'liquibase.gradle'
// check coverage limits locally with command '../gradlew cobertura coberturaCheck'
cobertura {
coberturaVersion = '2.1.1' // cobertura 2.1.x depends on asm-5 required for Java 8
coverageCheckHaltOnFailure = true // fail if coverage is below limits
coverageIgnoreTrivial = true // ignore simple getters and setters
coverageCheckBranchRate = 0 // minimum acceptable branch coverage rate (percent) needed by each class
coverageCheckLineRate = 0 // minimum acceptable line coverage rate (percent) needed by each class
coverageCheckTotalBranchRate = 50 // minimum acceptable branch coverage rate (percent) needed by the whole project
coverageCheckTotalLineRate = 50 // minimum acceptable line coverage rate (percent) needed by the whole project
coverageCheckRegexes = [
// more fine grained limits per package
[regex: 'com.infinit.atobcarry.config.*', branchRate: 0, lineRate: 0],
[regex: 'com.infinit.atobcarry.entity.*', branchRate: 0, lineRate: 0]
]
//exclude the fixture files in order to get a realistic view of the coverage
coverageExcludes = [
'.*\\.DevelopmentFixtures.*',
'.*\\.Fixtures.*'
]
}
letteral {
username = 'username'
password = 'pass'
organization = 'org'
repos = files('mail')
apiUrl = 'http://letteral-dev.elasticbeanstalk.com/api'
}
configurations {
webapp // configuration used to hold the build result of the client project
}
dependencies {
// spring boot dependencies
compile "org.springframework.boot:spring-boot-starter-data-jpa"
compile "org.springframework.boot:spring-boot-starter-security"
compile "org.springframework.boot:spring-boot-starter-web"
compile "org.springframework.boot:spring-boot-starter-actuator"
compile "org.springframework.boot:spring-boot-starter-security"
compile "org.springframework.boot:spring-boot-starter-websocket"
compile "org.springframework:spring-context-support"
compile "org.springframework:spring-messaging"
//compile("org.springframework.boot:spring-boot-devtools")
// modelmapper
compile "org.modelmapper.extensions:modelmapper-spring:0.7.3"
// swagger
compile "com.mangofactory:swagger-springmvc:1.0.0"
// database dependencies
compile 'com.h2database:h2:1.4.190'
// runtime 'org.postgresql:postgresql:9.4-1201-jdbc41'
// liquibase
runtime 'org.liquibase:liquibase-core:3.3.2'
// Joda
compile 'joda-time:joda-time:2.7'
compile 'org.jadira.usertype:usertype.spi:3.2.0.GA'
compile 'org.jadira.usertype:usertype.core:3.2.0.GA'
compile 'com.fasterxml.jackson.datatype:jackson-datatype-joda';
// Apache commons
compile 'org.apache.commons:commons-lang3:3.3.2'
compile 'org.apache.commons:commons-io:1.3.2'
// java melody dependencies
compile 'net.bull.javamelody:javamelody-core:1.55.0'
runtime 'com.thoughtworks.xstream:xstream:1.4.8'
runtime 'org.jrobin:jrobin:1.5.9'
// Atmosphere SSE / Websockets
compile 'org.atmosphere:atmosphere-runtime:2.2.6'
// Jackson
compile 'com.fasterxml.jackson.core:jackson-core'
// letteral
compile 'com.letteral:letteral-client-java:0.0.17'
// tomtom
compile(group: 'com.tomtomworker.webfleet.connect', name: 'webfleet-connect-client', version: '1.1')
//google maps
compile 'com.google.maps:google-maps-services:0.1.7'
//quartz
compile(group: 'org.quartz-scheduler', name: 'quartz', version: '2.2.1')
compile(group: 'org.quartz-scheduler', name: 'quartz-jobs', version: '2.2.1')
//itext pdf generation
compile('com.itextpdf:itextpdf:5.5.6')
//xdocreport templating over freemarker
compile('fr.opensagres.xdocreport:xdocreport:1.0.3')
compile('fr.opensagres.xdocreport:fr.opensagres.xdocreport.template:1.0.3')
compile('fr.opensagres.xdocreport:fr.opensagres.xdocreport.template.freemarker:1.0.3')
//unfortuately we also need to include the velocity templates without using them
compile('fr.opensagres.xdocreport:fr.opensagres.xdocreport.template.velocity:1.0.3')
compile('fr.opensagres.xdocreport:fr.opensagres.xdocreport.converter.odt.odfdom:1.0.3')
//pdf signing with bouncy castle, must be 1.49 for now as itext 5.5.6 only supports BC 1.49
compile('org.bouncycastle:bcpkix-jdk15on:1.49')
//jts to create the tunnel
compile('com.vividsolutions:jts:1.13')
compile('org.geotools:gt-shapefile:14.0')
//compile('org.geotools:gt-swing:13.3')
compile('org.geotools:gt-epsg-hsql:14.0')
//javaxmail
compile 'javax.mail:mail:1.4.1'
//hazelcast
compile("com.hazelcast:hazelcast-all:3.5") {
exclude group: 'org.freemarker'
}
// testing dependencies
testCompile("org.springframework.boot:spring-boot-starter-test") {
// the following artifacts are excluded since spock is used:
exclude group: 'org.mockito', module: 'mockito-core'
}
testCompile 'org.codehaus.groovy.modules.http-builder:http-builder:0.7.1'
testCompile 'org.spockframework:spock-spring:1.0-groovy-2.4'
testCompile 'com.jayway.jsonpath:json-path:0.9.1'
testCompile 'cglib:cglib-nodep:3.1'
testCompile 'org.dbunit:dbunit:2.4.9'
testCompile 'com.github.springtestdbunit:spring-test-dbunit:1.2.1'
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
// web resources from client project
webapp project(path: ':atobcarry-client', configuration: 'webapp')
}
// configure the war task to deploy on conventional servlet container (e.g. tomcat)
war {
// let war task depend on webapp configuration
// hereby start relevant tasks in the client project;
// when the war task runs execute the closure
// hereby unzip the client project's build result
// and add it to the resources path of the war
// This folder is exposed as static content by spring boot.
dependsOn(configurations.webapp)
from { zipTree(configurations.webapp.singleFile) }
baseName = 'atobcarry'
//version = '0.1.0'
}
// docker packaging requires a jar file that is configured similarly to the war
jar {
dependsOn(configurations.webapp)
from(zipTree(configurations.webapp.singleFile)) {
into 'META-INF/resources'
}
baseName = 'atobcarry'
//version = '0.1.0'
}
The application config:
mail.host=localhost
mail.from=organization#organization.de
organization.serverURL=http://localhost:8080
organization.enableTomTomTracking=false
organization.disableQuartzJobsInDebugMode=false
organization.restUrlTrackingPositions=http://localhost:8080/api/v1/trackingPositions/
organization.gracePeriodExpiredRequestsMinutes=1
organization.gracePeriodExpiredOffersMinutes=1
organization.keystorePath=security/atobcarry
organization.truststorePath=security/cacerts
organization.keyPassword=password
organization.keyAlias=organization
organization.keystorePassword=changeit
organization.pdfHashingAlgorithm=SHA-256
liquibase.changeLog=classpath:/db/changelog/db.changelog-master.xml
liquibase.enabled=false
management.security.enabled:false
letteral.enabled=false
letteral.from=support#organization.com
letteral.apiKey=123456
letteral.apiUrl=http://letteral-dev.elasticbeanstalk.com/api
letteral.hoursTokenValid=24
letteral.organization=organization
letteral.repository=mail
letteral.release=not used
letteral.releaseVersion=not used
letteral.requestMailName=request
# google maps properties
googleMaps.directionsApiKey=xxxxx
googleMaps.mode=car
# for debugging letteral requests
# logging.level.org.apache.http.wire=DEBUG
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.password=
spring.datasource.url=jdbc:h2:mem:devDb;MVCC=TRUE;LOCK_TIMEOUT=10000;MODE=PostgreSQL
spring.datasource.username=dbuser
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQL9Dialect
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.properties.hibernate.id.new_generator_mappings=true
#spring.jpa.show-sql=false
spring.jpa.open-in-view=true
spring.jpa.properties.jadira.usertype.autoRegisterUserTypes=true
spring.jpa.properties.jadira.usertype.databaseZone=UTC
spring.jpa.properties.jadira.usertype.javaZone=jvm
spring.jackson.dateFormat=yyyy-MM-dd'T'HH:mm:ss.SSS'Z'
spring.messages.basename=com/infinit/atobcarry/messages
multipart.maxFileSize=10Mb
That should be all relevant Information I hope. Please tell me if it isnt enought.
update: here are some more related files. What might be important: The Project contains 2 "subprojects": server and client. The Client is pure Javascript and works fine. The build.gradle above is the one from the server, I just added the main build.gradle and some other files as well.
application class:
#Configuration
#EnableJpaRepositories("com.infinit.atobcarry.repository")
#EnableAutoConfiguration
#EnableConfigurationProperties
#ComponentScan("com.infinit.atobcarry")
#EntityScan(basePackages = {"com.infinit.atobcarry.entity"})
#EnableJpaAuditing
#EnableAspectJAutoProxy
public class Application implements EmbeddedServletContainerCustomizer {
public final static String API_PREFIX = "/api/v1";
public final static String FRONTEND_PREFIX = "/#";
// As a default it is assumed that the document root is the app folder of the client project.
// Relative to the root of the project this is located in the following path:
private final static String CLIENT_DOCUMENT_ROOT = "../atobcarry-client/app";
/**
* An embedded container is started, when the application is run via the main method.
* It can be started with the gradle command bootRun
*
* #param args start parameters
* #throws Exception
*/
public static void main(String[] args) throws Exception {
SpringApplication app = new SpringApplication(Application.class);
app.run(args);
}
/**
* When running with an embedded servlet container additional configurations can be applied.
*
* #param container that is subject of the configuration
*/
#Override
public void customize(ConfigurableEmbeddedServletContainer container) {
// The embedded servlet container shall use the resources from the client project
configureDocumentRoot(container);
// send charset in Content-Type response header to improve performance
MimeMappings mappings = new MimeMappings(MimeMappings.DEFAULT);
mappings.add("html", "text/html;charset=utf-8");
container.setMimeMappings(mappings);
}
/**
* Sets the document root to the resource folder of the client project if available.
* This allows for instant reloading when developing the app.
*/
private void configureDocumentRoot(ConfigurableEmbeddedServletContainer container) {
String documentRootPath = CLIENT_DOCUMENT_ROOT;
File documentRoot = new File(documentRootPath);
if (documentRoot.isDirectory() && documentRoot.canRead()) {
container.setDocumentRoot(documentRoot);
}
}
}
here are some more information:
this class might be interesting as well:
/**
* Servlet 3.0+ environments allow to replace the web.xml file with a programmatic configuration.
* <p/>
* Created by owahlen on 01.01.14.
*/
public class Deployment extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
/**
* This method is copied from SpringBootServletInitializer.
* Only the registration of the ErrorPageFilter is omitted.
* This was done since errors shall never be sent as redirects but as ErrorDto
* #param servletContext
* #return
*/
protected WebApplicationContext createRootApplicationContext(ServletContext servletContext) {
SpringApplicationBuilder builder = new SpringApplicationBuilder();
ApplicationContext parent = getExistingRootWebApplicationContext(servletContext);
if (parent != null) {
this.logger.info("Root context already created (using as parent).");
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, null);
builder.initializers(new ParentContextApplicationContextInitializer(parent));
}
builder.initializers(new ServletContextApplicationContextInitializer(servletContext));
builder.contextClass(AnnotationConfigEmbeddedWebApplicationContext.class);
builder = configure(builder);
SpringApplication application = builder.build();
if (application.getSources().isEmpty()
&& AnnotationUtils.findAnnotation(getClass(), Configuration.class) != null) {
application.getSources().add(getClass());
}
Assert.state(application.getSources().size() > 0,
"No SpringApplication sources have been defined. Either override the "
+ "configure method or add an #Configuration annotation");
// Error pages are handled by the ExceptionHandlerController. No ErrorPageFilter is needed.
// application.getSources().add(ErrorPageFilter.class);
return run(application);
}
private ApplicationContext getExistingRootWebApplicationContext(ServletContext servletContext) {
Object context = servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
if (context instanceof ApplicationContext) {
return (ApplicationContext) context;
}
return null;
}
}
and another configuration - class:
#Configuration
public class H2Console {
protected final Logger logger = LoggerFactory.getLogger(getClass());
/**
* Define the H2 Console Servlet
*
* #return ServletRegistrationBean to be processed by Spring
*/
#Bean(name= "h2servlet")
public ServletRegistrationBean h2servletRegistration() {
ServletRegistrationBean registration = new ServletRegistrationBean(new WebServlet());
registration.addInitParameter("webAllowOthers", "true"); // allow access from URLs other than localhost
registration.addUrlMappings("/console/*");
return registration;
}
}
main build.gradle:
import java.util.concurrent.CountDownLatch
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'org.asciidoctor:asciidoctor-gradle-plugin:1.5.0'
}
}
apply plugin: 'org.asciidoctor.gradle.asciidoctor'
ext {
applicationVersion = 'UNDEFINED'
appBackend = null
}
asciidoctor {
sourceDir = file('asciidoc')
options = [
doctype : 'book',
attributes: [
'source-highlighter': 'coderay',
toc : '',
idprefix : '',
idseparator : '-'
]
]
}
def defaultEnvironment() {
def environment = ["PATH=${System.env.PATH}"]
environment += "HOME=${System.env.HOME}"
return environment
}
def execAsync(command, printStdOutput, dir, expectedOutput) {
println("Starting async command $command")
final CountDownLatch condition = new CountDownLatch(1)
def commandEnvironment = defaultEnvironment()
def proc = command.execute(commandEnvironment, new File(dir as String))
Thread.start {
try {
proc.in.eachLine { line ->
if (printStdOutput) {
println "$line"
}
if (expectedOutput != null && line?.contains(expectedOutput)) {
condition.countDown()
}
}
}
catch (ignored) {
}
}
Thread.start {
try {
proc.err.eachLine { line ->
if (printStdOutput) {
println line
}
}
}
catch (ignored) {
}
}
return [proc, expectedOutput != null ? condition : null]
}
task startServer() {
doLast {
def condBackend
(appBackend, condBackend) = execAsync(["./gradlew", "run"], true, "$projectDir", "Started Application")
condBackend.await()
}
}
task stopProcesses << {
appBackend?.destroy()
}
task e2eReport(dependsOn: [startServer, ':atobcarry-client:clean', ':project-client:e2eTest'])
tasks.getByPath(':project-client:e2eTest').mustRunAfter(startServer)
stopProcesses.mustRunAfter(':project-client:e2eTest')
startServer.finalizedBy(stopProcesses)
e2eReport.finalizedBy(stopProcesses)
tasks.getByPath(':project-client:e2eTest').finalizedBy(stopProcesses)
task validate(dependsOn: [':project-client:grunt_default', ':project-server:cobertura', ':project-server:coberturaCheck'])
the settings.gradle:
// This file includes the gradle subprojects of project project
include 'project-server' // REST webserver backend (WAR)
include 'project-client' // AngularJS frontend (JAR)
include 'project-tracking' // TomTom tracking server (WAR)
include 'project-tracking-commons' // Shared code between tracking and server
querydsl.graddle (from project-server)
configurations {
// configuration to hold the build dependency on the querydsl generator
querydslapt
}
String queryDslVersion = '3.5.1'
dependencies {
querydslapt "com.mysema.querydsl:querydsl-apt:$queryDslVersion"
compile "com.mysema.querydsl:querydsl-jpa:$queryDslVersion"
}
task generateQueryDSL(type: JavaCompile, group: 'build', description: 'Generate the QueryDSL query types.') {
// only process entity classes and enums to avoid compilation errors from code that needs the generated sources
source = fileTree('src/main/java/com/infinit/atobcarry/entity') + fileTree('src/main/java/com/infinit/project/enums')
// include the querydsl generator into the compilation classpath
classpath = configurations.compile + configurations.querydslapt
options.compilerArgs = [
"-proc:only",
"-processor", "com.mysema.query.apt.jpa.JPAAnnotationProcessor"
]
options.warnings = false
// the compiler puts the generated sources into the gensrcDir
destinationDir = gensrcDir
}
gensrc {
// extend the gensrc task to also generate querydsl
dependsOn generateQueryDSL
}
liquibase.graddle (from server)
configurations {
liquibase
}
dependencies {
liquibase 'org.liquibase:liquibase-core:3.3.2'
liquibase 'org.liquibase.ext:liquibase-hibernate4:3.5'
// liquibase 'org.yaml:snakeyaml:1.14'
liquibase 'org.postgresql:postgresql:9.3-1103-jdbc41'
liquibase 'org.springframework:spring-beans'
liquibase 'org.springframework:spring-orm'
liquibase 'org.springframework:spring-context'
liquibase 'org.springframework.boot:spring-boot' // contains the SpringNamingStrategy
liquibase 'org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.0.Final'
}
[
'status' : 'Outputs count (list if --verbose) of unrun change sets.',
'validate' : 'Checks the changelog for errors.',
'changelogSync' : 'Mark all changes as executed in the database.',
'changelogSyncSQL' : 'Writes SQL to mark all changes as executed in the database to STDOUT.',
'listLocks' : 'Lists who currently has locks on the database changelog.',
'releaseLocks' : 'Releases all locks on the database changelog.',
'markNextChangesetRan' : 'Mark the next change set as executed in the database.',
'markNextChangesetRanSQL': 'Writes SQL to mark the next change set as executed in the database to STDOUT.',
'dropAll' : 'Drops all database objects owned by the user. Note that functions, procedures and packages are not dropped (limitation in 1.8.1).',
'clearChecksums' : 'Removes current checksums from database. On next run checksums will be recomputed.',
'generateChangelog' : 'generateChangeLog of the database to standard out. v1.8 requires the dataDir parameter currently.',
'futureRollbackSQL' : 'Writes SQL to roll back the database to the current state after the changes in the changeslog have been applied.',
'update' : 'Updates the database to the current version.',
'updateSQL' : 'Writes SQL to update the database to the current version to STDOUT.',
'updateTestingRollback' : 'Updates the database, then rolls back changes before updating again.',
'diff' : 'Writes description of differences to standard out.',
'diffChangeLog' : 'Writes Change Log XML to update the base database to the target database to standard out.',
'updateCount' : 'Applies the next <liquibaseCommandValue> change sets.',
'updateCountSql' : 'Writes SQL to apply the next <liquibaseCommandValue> change sets to STDOUT.',
'tag' : 'Tags the current database state with <liquibaseCommandValue> for future rollback',
'rollback' : 'Rolls back the database to the state it was in when the <liquibaseCommandValue> tag was applied.',
'rollbackToDate' : 'Rolls back the database to the state it was in at the <liquibaseCommandValue> date/time.',
'rollbackCount' : 'Rolls back the last <liquibaseCommandValue> change sets.',
'rollbackSQL' : 'Writes SQL to roll back the database to the state it was in when the <liquibaseCommandValue> tag was applied to STDOUT.',
'rollbackToDateSQL' : 'Writes SQL to roll back the database to the state it was in at the <liquibaseCommandValue> date/time to STDOUT.',
'rollbackCountSQL' : 'Writes SQL to roll back the last <liquibaseCommandValue> change sets to STDOUT.'
].each { String taskName, String taskDescription ->
String prefixedTaskName = 'dbm' + taskName.capitalize()
task(prefixedTaskName, type: JavaExec) { JavaExec task ->
initLiquibaseTask(task)
args += taskName
String liquibaseCommandValue = project.properties.get("liquibaseCommandValue")
if (liquibaseCommandValue) {
args += liquibaseCommandValue
}
}
}
void initLiquibaseTask(JavaExec task) {
String changeLogFile = 'src/main/resources/db/changelog/db.changelog-master.xml'
task.main = 'liquibase.integration.commandline.Main'
task.classpath = configurations.liquibase + sourceSets.main.runtimeClasspath
task.args = [
// "--logLevel=debug",
"--changeLogFile=${changeLogFile}",
"--url=jdbc:postgresql://localhost:15432/roject",
"--username=project",
"--password=project",
"--referenceUrl=hibernate:spring:com.infinit.atobcarry?dialect=org.hibernate.dialect.PostgreSQL9Dialect&hibernate.ejb.naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringNamingStrategy&hibernate.enhanced_id=true",
]
task.group = 'liquibase'
}
jreleaseinfo.gradle
configurations {
// configuration to hold the build dependency on the jreleaseinfo ant task
jreleaseinfo
}
dependencies {
jreleaseinfo 'ch.oscg.jreleaseinfo:jreleaseinfo:1.3.0'
}
task generateJReleaseInfo(group: 'build', description: 'Generate the VersionInfo class.') { Task task ->
Map<String, ?> parameters = [
buildKey: project.hasProperty('buildKey') ? project.buildKey : '',
buildResultKey: project.hasProperty('buildResultKey') ? project.buildResultKey : '',
buildNumber: project.hasProperty('buildNumber') ? project.buildNumber : '',
buildResultsUrl: project.hasProperty('buildResultsUrl') ? project.buildResultsUrl : '',
gitBranch: project.hasProperty('gitBranch') ? project.gitBranch : '',
gitCommit: project.hasProperty('gitCommit') ? project.gitCommit : ''
]
task.inputs.properties(parameters)
task.inputs.property('version', project.version)
task.outputs.file( new File(gensrcDir, 'com/infinit/atobcarry/config/VersionInfo.java') )
task.doLast {
// gradle properties that can be passed to the JReleaseInfoAntTask task
ant.taskdef(name: 'jreleaseinfo', classname: 'ch.oscg.jreleaseinfo.anttask.JReleaseInfoAntTask', classpath: configurations.jreleaseinfo.asPath)
ant.jreleaseinfo(targetDir: gensrcDir, className: 'VersionInfo', packageName: 'com.infinit.atobcarry.config', version: project.version) {
parameters.each { String key, String value ->
parameter(name: key, type: 'String', value: value)
}
}
}
}
gensrc {
// extend the gensrc task to also generate JReleaseInfo
dependsOn generateJReleaseInfo
}
gensrc.gradle
// register directory where generated sources are located with the project
ext.gensrcDir = file('src/main/generated')
// create a wrapper task for source generation that the generators can depend upon
task gensrc(group: 'build', description: 'Execute all tasks that generate source code.')
// include the source code generators
apply from: 'querydsl.gradle'
apply from: 'jreleaseinfo.gradle'
// add the gensrcDir to the sourceSets
sourceSets {
generated
}
sourceSets.generated.java.srcDirs = [gensrcDir]
// extend the conventional compileJava task to also compile the generated sources
compileJava {
dependsOn gensrc
source gensrcDir
}
clean {
delete gensrcDir
}
orm.xml
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_2_0.xsd"
version="2.0">
<persistence-unit-metadata>
<persistence-unit-defaults>
<entity-listeners>
<entity-listener class="org.springframework.data.jpa.domain.support.AuditingEntityListener"/>
</entity-listeners>
</persistence-unit-defaults>
</persistence-unit-metadata>
</entity-mappings>

Categories