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>
Related
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.
I'm experimenting with gradle and trying to setup a system that builds different flavors (brands) of an application, which differ by configuration mainly. What I have so far are two versions of the build scripts - both not working.
Version 1
First flavor specific resource folder flavor-res is added to sourcesets, which achieves overwriting some default resources. A task rule defines tasks for each flavor, which should (ideally) trigger build of the whole jar.
This works fine and generates the required jar, for one flavor at a time, like
gradle clean flavorOne
but the shadowJar task runs only once, if I do
gradle clean flavorOne flavorTwo
Stripped down Script:
sourceSets {
main {
...
resources {
srcDirs = ['src/main/resources', "${project.buildDir}/flavor-res/"]
}
}
}
shadowJar { classifier = 'SNAPSHOT' }
tasks.addRule("Pattern: flavor<Name>") { String taskName ->
if (taskName.startsWith("flavor")) {
String flavorName = (taskName - "flavor")
String flavorOutDir = "${project.buildDir}/${flavorName}"
// Set output folder and jar name
task("${taskName}Configure") {
outputs.dir(flavorOutDir)
doFirst {
archivesBaseName = flavorName
project.buildDir = flavorOutDir
}
}
// Copy res to folder used in sourcesets
task("${taskName}CopyResources") {
mustRunAfter = ["${taskName}Configure"]
outputs.dir("${project.buildDir}/flavor-res")
doFirst {
copy {
from "flavors/${flavorName}/"
into "${project.buildDir}/flavor-res/"
}
}
}
shadowJar.mustRunAfter = ["${taskName}Configure", "${taskName}CopyResources"]
// Define task that depends on shadowJar
task(taskName, dependsOn: ["${taskName}Configure", "${taskName}CopyResources",
shadowJar]) {
println "Configuring ${taskName}"
}
}
Sensing that it probably doesnt work because the change detection somehow doesnt work, I tried an alternative approach. Here is a simplified version of script
Version 2
Modified the rule to define a shadowJar dynamic task for each flavor.
/* Removed sourceSets in this version */
shadowJar { classifier = 'SNAPSHOT' }
tasks.addRule("Pattern: flavor<Name>") { String taskName ->
if (taskName.startsWith("flavor")) {
String flavorName = (taskName - "flavor")
String flavorOutDir = "${project.buildDir}/${flavorName}"
// Set resources for main sourceset
task("${taskName}Configure") {
outputs.dir(flavorOutDir)
doFirst {
archivesBaseName = flavorName
sourceSets.main.resources.srcDirs = ['src/main/resources', "${flavorOutDir}/flavor-res"]
project.buildDir = flavorOutDir
}
}
task("${taskName}CopyResources") {
outputs.dir("${flavorOutDir}/flavor-res")
dependsOn "${taskName}Configure"
doFirst {
copy {
from "flavors/${flavorName}/"
into "${project.buildDir}/flavor-res/"
}
}
}
// This should shadowJar for each flavor - but generate jars dont have the required artifacts.
task ("${taskName}Build", type: ShadowJar) {
from sourceSets.main.output
configurations = [ configurations.runtime ]
classifier = 'SNAPSHOT'
dependsOn "${taskName}CopyResources"
}
task(taskName, dependsOn: ["${taskName}Build"]) {
}
}
}
However, now, the generated jars are malformed. The first flavor gets just the artifacts for main, but no showed jars. The second jar has just the manifest and nothing else.
What would be the correct way of achieving that.
PS: No, its not an android application (flavor is just a synonym for a brand).
I decided to recreate a flavor build script, because it can be simplified to what you have now. The ShadowJar task can handle copying all the classes and resources by itself, there is no need to define separate ones. I also took some default configuration that would have been applied to the shadowJar task and applied this to the custom ShadowJar tasks to get the same behavior.
I first build a quick test project structure which can be found here:
Test Structure
Then I came up with the following script:
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
plugins {
id 'java'
id "com.github.johnrengelman.shadow" version "2.0.4"
}
group 'your-group'
version 'dev-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
// Example dependency
compile group: 'com.google.guava', name: 'guava', version: '19.0'
}
tasks.addRule("Pattern: flavor<Name>") { def taskName ->
if (!taskName.startsWith("flavor")) {
return
}
def flavorName = taskName - "flavor"
// Define the shadow task
def shadowTask = task ("${flavorName}ShadowJar", type: ShadowJar) {
classifier = flavorName
// Add our flavor resources, first to prioritize these resources
from file("src/main/flavors/${flavorName}")
// Include our project classes
from project.sourceSets.main.output
// Don't include duplicate resources, only the first ones added, in
// this case the flavored resources will override the default ones
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
// Some defaults taken from the default shadowJar task
// https://github.com/johnrengelman/shadow/blob/master/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.groovy#L48
configurations = [ project.configurations.runtime ]
manifest.inheritFrom project.tasks.jar.manifest
exclude('META-INF/INDEX.LIST', 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA')
}
// Define the flavor task
task ("${taskName}", dependsOn: shadowTask) {}
}
I have integrated QueryDSL into my Spring boot project.
build.gradle:
//dependencies
compile("com.mysema.querydsl:querydsl-jpa:3.7.4")
compile("com.mysema.querydsl:querydsl-apt:3.7.4:jpa")
idea {
module {
sourceDirs += file('src/main/generated/')
generatedSourceDirs += file('src/main/generated/')
}
}
The generated .class and .java (Q classes) files are currently deployed into build/classes/main/my/package/model where the entity class files are created.
How can I configure the JPAAnnotationProcessor to put generated sources(e.g. QMyEntity.java) into src/main/generated?
You could try something like that (hard way):
def queryDslOutput = file("src/main/generated")
sourceSets {
main {
java {
srcDir queryDslOutput
}
}
}
task generateQueryDSL(type: JavaCompile, group: 'build') {
source = sourceSets.main.java
classpath = configurations.compile
destinationDir = queryDslOutput
options.compilerArgs = [
"-proc:only",
"-processor", 'com.querydsl.apt.jpa.JPAAnnotationProcessor,lombok.launch.AnnotationProcessorHider$AnnotationProcessor'
]
}
compileJava.dependsOn(generateQueryDSL)
clean {
delete queryDslOutput
}
The compiler options are required if you are using lombok.
Or if you are using the querydsl-plugin you could configure the output directory (easy way):
def generatedClassesPath= "build/generated/source/querydsl/main"
querydsl {
jpa = true
querydslSourcesDir = generatedClassesPath
}
You could always add generated sources to classpath to catch the files by Intellij Idea:
def queryDslOutput = file(generatedClassesPath)
sourceSets {
main {
java {
srcDir queryDslOutput
}
}
}
From plugin documentation:
querydslSourcesDir
The project relative path to where the querydsl
meta model sources are created in. It does not matter which annotation
processors are used, all meta model classes will be created within
this directory.
Defaults to src/querydsl/java.
I have a Spring Boot + Angular 2 project. I want to deploy it to Heroku.
I'm able to run the npm build then copy the generated files over to the public folder (src/resources/public) manually, then run the backend build.
What I want to do is to set up a gradle build that will do all of that at once.
What I have so far is a gradle build that will build the front end, build the backend, however it does not copy the static files before generating the jar. Since the jar does not contain said static files, it won't work on Heroku.
Here's the project folder structure:
root
backend
src/main/java
src/main/resources
frontend
--> angular files go here
build/libs -> where the JAR file goes
The gradle build file:
buildscript {
repositories {
mavenCentral()
}
dependencies {
// spring
classpath('org.springframework.boot:spring-boot-gradle-plugin:1.5.2.RELEASE')
classpath('org.springframework:springloaded:1.2.6.RELEASE')
}
}
plugins {
id "com.moowork.node" version "1.2.0"
}
// gradle wrapper
task wrapper(type: Wrapper) {
gradleVersion = '3.4'
}
// configure gradle-node-plugin
node {
version = '8.1.4'
npmVersion = '5.0.3'
download = true
workDir = file("${project.projectDir}/node")
nodeModulesDir = file("${project.projectDir}/")
}
// clean node/node_modules/dist
task npmClean(type: Delete) {
final def webDir = "${rootDir}/frontend"
delete "${webDir}/node"
delete "${webDir}/node_modules"
delete "${webDir}/dist"
delete "${webDir}/coverage"
delete "${rootDir}/backend/src/main/resources/public"
}
// clean task for npm
task copyFiles {
doLast {
copy {
from "${rootDir}/frontend/dist"
into "${rootDir}/backend/src/main/resources/public"
}
}
}
// build task for npm
task frontendBuild {}
frontendBuild.dependsOn(npm_install)
frontendBuild.dependsOn(npm_run_build)
npm_install {
args = ['--prefix', './frontend']
}
npm_run_build {
args = ['--prefix', './frontend']
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
sourceSets {
main {
java {
srcDirs = ['backend/src/main/java']
}
resources {
srcDirs = ['backend/src/main/resources']
}
}
}
copyFiles.dependsOn(frontendBuild);
compileJava.dependsOn(frontendBuild);
task backendBuild {}
backendBuild.dependsOn(compileJava)
backendBuild.dependsOn(jar)
jar.dependsOn(copyFiles)
repositories {
mavenCentral()
}
eclipse {
classpath {
containers.remove('org.eclipse.jdt.launching.JRE_CONTAINER')
containers('org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8')
}
}
idea {
module {
inheritOutputDirs = false
outputDir = file("${buildDir}/classes/main/")
}
}
jar {
baseName = 'expense-splitter'
version = '0.0.1'
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
configurations {
dev
}
dependencies {
// spring
compile('org.springframework.boot:spring-boot-starter-web:1.5.2.RELEASE')
compile('org.springframework.boot:spring-boot-starter-data-jpa:1.5.2.RELEASE')
compile('org.springframework.boot:spring-boot-starter-security:1.5.2.RELEASE')
compile('org.apache.commons:commons-lang3:3.3.2')
// to make hibernate handle java 8 date and time types correctly
// it's marked as deprecated but we need to keep it until
// spring boot jpa starts using hibernate 5.2
compile('org.hibernate:hibernate-java8:5.1.0.Final')
// json web tokens
compile ('io.jsonwebtoken:jjwt:0.7.0')
compile 'mysql:mysql-connector-java'
// google gson
compile('com.google.code.gson:gson:2.8.0')
// jackson - parsing of java 8 date and time types
compile('com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.8.7')
// spring dev tools
dev('org.springframework.boot:spring-boot-devtools:1.5.2.RELEASE')
// testing
testCompile('org.springframework.boot:spring-boot-starter-test:1.5.2.RELEASE')
}
// run spring boot app
bootRun {
//addResources = true
classpath = sourceSets.main.runtimeClasspath + configurations.dev
jvmArgs = ["-Xdebug -agentlib:jdwp=transport=dt_socket,address=8080,server=y,suspend=n"]
}
// run all task
task runAll {}
runAll.dependsOn(bootRun)
Thanks in advance,
Try a different approach. Instead of manually copying the resources, tell Gradle that when it processes resources for the JAR, also take into consideration what is in frontend/dist/:
processResources {
from ('frontend/dist/') {
into 'public'
}
}
This should result in a JAR containing a public/ directory, with the contents of frontend/dist/ inside of it.
Gradle configuration for Spring Boot 1.5\2.x + Angular 2-6
Angular in sub-folder frontend
Frontend module
Crate build.gradle:
plugins {
id "com.moowork.node" version "1.2.0"
}
node {
version = '8.11.3'
npmVersion = '5.6.0'
download = true
workDir = file("${project.buildDir}/node")
nodeModulesDir = file("${project.projectDir}")
}
task build(type: NpmTask) {
args = ['run', 'build']
}
build.dependsOn(npm_install)
Note for Angular 6
Update outputPath value in angular.json to 'dist'
Backend module
Edit build.gradle for backend module:
Spring Boot 2.X:
bootJar {
archiveName = "yourapp.jar"
mainClassName = 'com.company.app.Application'
from('frontend/dist') {
into 'static'
}
}
Spring Boot 1.5.X:
jar {
archiveName = "yourapp.jar"
manifest {
attributes 'Main-Class': 'com.company.app.Application'
}
from('frontend/dist') {
into 'static'
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}
Finally execute bootRepackage or bootJar task and check results in builds/libs
Assume that front end is located at the following folder: src/main/webapp/fe-ui/, the following solution for the Spring Boot version 2.1.1.RELEASE could be considered:
bootJar {
baseName = 'jar-name'
version = '0.1.0'
from('src/main/webapp/fe-ui/build') {
into 'public'
}
}
task installFeDependencies(type: NpmTask) {
args = ['install']
}
task buildFe(type: NpmTask) {
args = ['run', 'build']
dependsOn installFeDependencies
}
compileJava {
dependsOn buildFe
}
Running gradlew build will install, build front end as well as will invoke bootJar. The latter will package built front end bundle.
I'm trying to setup Gradle to run Android test using Roboelectric mocking framework.
I have an Eclipse workspace with this structure:
MyApp
src
gen
test
....
MyAppTest
libs
test (source folder linked to MyApp.test)
....
Tests runs fine in Eclipse manually configuring build path.
How can I configure Gradle build scripts in MyAppTest to run tests in MyApp project using Roboelectric?
I was able to get this working based on this solution
In summary, try adding the following to your build.gradle:
sourceSets {
testLocal {
java.srcDir file('src/test/java')
resources.srcDir file('src/test/resources')
}
}
dependencies {
// Dependencies for your production code here.
compile 'some.library'
// localTest dependencies, including dependencies required by production code.
testLocalCompile 'some.library'
testLocalCompile 'junit:junit:4.11'
testLocalCompile 'com.google.android:android:4.1.1.4'
testLocalCompile 'org.robolectric:robolectric:2.2'
}
task localTest(type: Test, dependsOn: assemble) {
testClassesDir = sourceSets.testLocal.output.classesDir
android.sourceSets.main.java.srcDirs.each { dir ->
def buildDir = dir.getAbsolutePath().split('/')
buildDir = (buildDir[0..(buildDir.length - 4)] + ['build', 'classes', 'debug']).join('/')
sourceSets.testLocal.compileClasspath += files(buildDir)
sourceSets.testLocal.runtimeClasspath += files(buildDir)
}
classpath = sourceSets.testLocal.runtimeClasspath
}
check.dependsOn localTest
Don't forget to alter your *Test.java to #RunWith(RobolectricGradleTestRunner.class):
public class RobolectricGradleTestRunner extends RobolectricTestRunner {
public RobolectricGradleTestRunner(Class<?> testClass) throws InitializationError {
super(testClass);
}
#Override
protected AndroidManifest getAppManifest(Config config) {
String pwd = YourApplication.class.getProtectionDomain().getCodeSource().getLocation().getPath();
String root = pwd + "../../../src/main/";
return new AndroidManifest(
Fs.fileFromPath(root + "AndroidManifest.xml"),
Fs.fileFromPath(root + "res"),
Fs.fileFromPath(root + "assets"));
}
}
You will then be able to run your test via gradle compileDebugJava localTest. If I remember correctly, this will require a newer version of gradle (perhaps 1.8 or 1.9)