Gradle and Flyway: Unable to obtain inputstream for resource - gradle

I have the problem that migrateDb using Flyway in a Gradle project sometimes causes
Unable to obtain inputstream for resource: META-INF/db/mysql/V1__script.sql
This error doesn't occur all the time but only sometimes but if it happens it's quite persistent and also a clean/rebuild of the project doesn't solve it.
The SQL script that is mentioned is contained within a JAR file that is referenced from the project as part of a multi module project.
My researched only brought me to https://github.com/flyway/flyway/issues/702 but this didn't lead me to the right way.
I'm also very confused that flyway is able to find the file during the classpath search but is then not able to get the input stream.
If you should need any further info please ask.
Further debugging: It seems that the error seems to happen as soon as a new file is added to the DB JAR. After rebuild and migrateDb the error occurs. If I remove the script again the error still occurs although the script is not in the generated JAR anymore. So I guess the classpath for searching for scripts and retrieving input stream is different. Does anybody know what differences there might be?
Complete stack trace:
Caused by: org.flywaydb.core.api.FlywayException: Unable to obtain inputstream for resource: META-INF/db/mysql/V1__script.sql
at org.flywaydb.core.internal.util.scanner.classpath.ClassPathResource.loadAsString(ClassPathResource.java:84)
at org.flywaydb.core.internal.resolver.sql.SqlMigrationResolver.scanForMigrations(SqlMigrationResolver.java:139)
at org.flywaydb.core.internal.resolver.sql.SqlMigrationResolver.resolveMigrations(SqlMigrationResolver.java:99)
at org.flywaydb.core.internal.resolver.sql.SqlMigrationResolver.resolveMigrations(SqlMigrationResolver.java:49)
at org.flywaydb.core.internal.resolver.CompositeMigrationResolver.collectMigrations(CompositeMigrationResolver.java:122)
at org.flywaydb.core.internal.resolver.CompositeMigrationResolver.doFindAvailableMigrations(CompositeMigrationResolver.java:104)
at org.flywaydb.core.internal.resolver.CompositeMigrationResolver.resolveMigrations(CompositeMigrationResolver.java:90)
at org.flywaydb.core.internal.resolver.CompositeMigrationResolver.resolveMigrations(CompositeMigrationResolver.java:43)
at org.flywaydb.core.internal.info.MigrationInfoServiceImpl.refresh(MigrationInfoServiceImpl.java:114)
at org.flywaydb.core.internal.command.DbValidate$2.call(DbValidate.java:164)
at org.flywaydb.core.internal.command.DbValidate$2.call(DbValidate.java:157)
at org.flywaydb.core.internal.util.jdbc.TransactionTemplate.execute(TransactionTemplate.java:75)
at org.flywaydb.core.internal.command.DbValidate.validate(DbValidate.java:157)
at org.flywaydb.core.Flyway.doValidate(Flyway.java:1280)
at org.flywaydb.core.Flyway.access$100(Flyway.java:71)
at org.flywaydb.core.Flyway$1.execute(Flyway.java:1176)
at org.flywaydb.core.Flyway$1.execute(Flyway.java:1168)
at org.flywaydb.core.Flyway.execute(Flyway.java:1650)
at org.flywaydb.core.Flyway.migrate(Flyway.java:1168)
at org.flywaydb.gradle.task.FlywayMigrateTask.run(FlywayMigrateTask.java:28)
at org.flywaydb.gradle.task.AbstractFlywayTask.runTask(AbstractFlywayTask.java:382)
Gradle Task:
// task that migrates the database
task migrateDb(type: org.flywaydb.gradle.task.FlywayMigrateTask) {
// parse hibernate config
def hibernateConfig = parseHibernateConfigByStageParameter()
// set config
url = hibernateConfig.url
driver = hibernateConfig.driver
user = hibernateConfig.username
password = hibernateConfig.password
locations = [ "classpath:${flywayDbPath}/${hibernateConfig.dbType}" ]
table = 'schema_version'
outOfOrder = true
ignoreMissingMigrations = true
}
Gradle dependency:
// dependencies
dependencies {
[...]
runtime project(':core:db:mysql')
[...]
}

During further testing I noticed that the error seems to be because of the Gradle Daemon. Adding --no-daemon to the migrateDb call works fine and doesn't trigger the error.
That's fine for me for now.

It turns out that I was deploying and old .war, which was built with some .sql files that were not around anymore.
Then I fixed this by running gradlew clean build

Related

How can I use a maven dependency package that has been published to GitLab with Gradle Kotlin?

(for reference I am using: IntelliJ as my IDE, Kotlin as the language, and Gradle Kotlin for build)
The package is successfully published to the GitLab Project's Package Registry, it is listed as a Maven. I can download and access the .pom/.jar/.module file in the GitLab Package Registry, additionally the link to the gitlab repo .pom file (as in the error message below) when clicked will download the .pom for the package (this has me super confused). However when I want to use it as a dependency in a different project it cannot be resolved. I am using an Access Token for authentication of this project. This is the error I am getting when I attempt to build / sync my gradle project:
Execution failed for task ':compileKotlin'.
> Error while evaluating property 'filteredArgumentsMap' of task ':compileKotlin'
> Could not resolve all files for configuration ':compileClasspath'.
> Could not find <group>:<projectName>:<version>.
Searched in the following locations:
- https://repo.maven.apache.org/maven2/com/example/<projectName>/<version>/<projectName>-<version>.pom
- https://gitlab.com/api/v4/projects/<packageID>/packages/maven/com/example/<projectName>/<version>/<projectName>-<version>.pom
Required by:
project :
Possible solution:
- Declare repository providing the artifact, see the documentation at https://docs.gradle.org/current/userguide/declaring_repositories.html
(The group, projectName and version are all filled in with the those things for the project)
I did read the documentation provided as a possible solution as well as a large number of other sources with potential fixes or ways of setting it up, however I cannot seem to find how to solve or correctly import and use my maven repo. Other sources that I have already checked out / tried to use are:
https://www.jetbrains.com/help/space/publish-artifacts-from-a-gradle-project.html#publish-maven-artifacts-using-the-gradle-command-line-tool
https://gitlab-docs.creationline.com/ee/user/packages/maven_repository/
This is what I have in my gradle.build.kts of the package which is attempting to import / use the dependency (again of course packageName, group, version etc are filled in)
val gitLabAccessToken: String by project
repositories {
mavenCentral()
maven {
url = uri("https://gitlab.com/api/v4/projects/<projectID>/packages/maven")
name = "GitLab"
credentials(HttpHeaderCredentials::class) {
name = "Deploy Token"
value = gitLabAccessToken
}
authentication {
create<HttpHeaderAuthentication>("header")
}
}
}
I'm certain I am missing something silly and small, if there is anything more that is needed to get this working so that I can import and use it I will be happy to provide.
I knew it was something stupid, thank you #aSemy, It was that I had missed the dash between Deploy and Token (Deploy Token -> Deploy-Token) and that fixed it. I cannot believe I wasted hours over a dash.
The Solution to this Problem is adding the dash between Deploy and Token.
User #aSemy noticed this when I did not.

Dependencies put twice into Spring Boot (>2.x) jar when using Gradle

adding Cloud SDK like this for CF:
compile "com.sap.cloud.s4hana:s4hana-all:${cloudSDKVersion}"
compile ("com.sap.cloud.s4hana.cloudplatform:scp-cf:${cloudSDKVersion}")
leads to duplicate jars in spring boot jar which is deployed to CF.
examples:
core-2.3.1.jar
connectivity-2.3.1.jar
This leads to :
ClassNotFoundExceptions during runtime
prevents cf push commands with error:
Comparing local files to remote cache...
Aborting push: File BOOT-INF/lib/core-2.3.1.jar has been modified since the start of push. Validate the correct state of the file and try again.
FAILED
gradle skips the component name when building the boot package.
After some googling around this was the solution:
https://github.com/spring-projects/spring-boot/issues/10778
bootJar {
rootSpec.filesMatching('**/*.jar', { jar ->
String groupId = jar.file.parentFile.parentFile.parentFile.parentFile.name
jar.name = "$groupId-${jar.name}"
})
}

Grails 3 (Gradle) dependency without parent directory

Can I not use the following Gradle approach to dependencies in Grails? I do not have nor want a parent directory;
https://stackoverflow.com/a/19303545/2288004
When I try it, I get the the following error;
Caused by: java.lang.IllegalStateException: Expected method not found:
java.lang.NoSuchMethodException:
org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedContext.addApplicationListener(org.apache.catalina.deploy.ApplicationListener)
It works when I use a parent directory for the settings.gradle, but unfortunately it’s not how I want to structure the project.
The following was indeed the solution I was looking for,
include ":myplugin"
project(':myplugin').projectDir = new File(settingsDir, '../myplugin')
The error was down to how I was managing my tomcat dependencies between the two projects.
Tomcat was already being pulled in via the plugin but while I still needed to reference tomcat at compile time in the application, I also needed to make sure it was the same version, and so added the following just above "dependencies" to target the version I required;
ext['tomcat.version'] = '7.0.70'

Resolve a dependency dynamically inside a gradle task

I am trying to build a gradle plugin, which does the following:
As part of one its tasks, it creates a new configuration
It adds a DefaultExternalModuleDependency to this configuration - more specifically, it constructs a dependency to the application server zip file (available on Nexus). This information can be overridden by the invoking project as well.
Tries to resolve this newly added dependency and then unpacks the file to a local folder
All of this was working well when I had the details hard coded in a build file, but it looks like adding dependencies as part of a task are not treated the same way as having that information available at the parsing time.
So my question is, how do I get the project to reload the configurations / dependencies?
The code looks like the following:
#TaskAction
void installAppserver() {
Dependency dependency = new DefaultExternalModuleDependency(group,name,version)
Configuration configuration = project.configurations.detachedConfiguration(dependency)
configuration.setTransitive(false)
configuration.files.each { file ->
if (file.isFile() && file.name.endsWith('.zip')) {
println 'Attempting to unzip: ' + file + ' into folder: ' + appServerFolder
new Copy().from(project.zipTree(file)).into(appServerFolder).execute()
}
}
}
The problem is that the actual artifacts are not getting resolved!
A task can't configure the build model (that's what plugins do). It's fine to create and resolve a detached configuration in a task. If this doesn't work, there is likely a problem with the task's code, or the dependency it tries to resolve. Note that dependencies can only be resolved if the correct repository(s) are defined.
Instead of new DetaultExternalModuleDependency() (which is an internal class), project.dependencies.create() should be used. Instead of new Copy().execute() (Task#execute must not be called from user code), project.copy should be used.

OSGi bundle build issue in Gradle

I have a simple use case of building an OSGi bundle using Gradle build tool. The build is successful if there are java files present in the build path, but it fails otherwise.
I am using 'osgi' plugin inside the gradle script and trying to build without any java files. The build always fails with following error:
Could not copy MANIFEST.MF to
I am sure there must be some way to do it in Gradle but not able to fine. Any idea what can be done to resolve this depending on your experience.
I ran into this today as well, and #Peter's fix didn't work for me (I hadn't applied the java plugin in the first place...). However, after hours of Googling I did find this thread, which helped me find the problem.
Basically, it seems that the error occurs (as Peter stated) when no class files are found in the jar - my guess is because the plugin then cannot scan the classes for package names on which to base all the Import and Export information.
My solution was to add the following to the manifest specification:
classesDir = theSourceSet.output.classesDir
classpath = theSourceSet.runtimeClasspath
In my actual build code, I loop over all source sets to create jar tasks for them, so then it looks like this:
sourceSets.each { ss ->
assemble.dependsOn task("jar${ss.name.capitalize()}", type: Jar, dependsOn: ss.getCompileTaskName('Java')) {
from ss.output
into 'classes'
manifest = osgiManifest {
classesDir = ss.output.classesDir
classpath = ss.runtimeClasspath
// Other properties, like name and symbolicName, also set based on
// the name of the source set
}
baseName = ss.name
}
}
Running with --stacktrace indicates that the osgi plugin doesn't deal correctly with the case where both the osgi and the java plugins are applied, but no Java code is present. Removing the java plugin should solve the problem.
I had the same issue also when java code was present.
Adding these two lines to the osgiManifest closure fixed the problem:
classesDir = sourceSets.main.output.classesDir
classpath = sourceSets.main.runtimeClasspath
-- erik

Resources