1

I have recently migrated my app to spring Boot 3 and now trying to integrate the native build into the release process.

Right now I am facing an issue with some of the files from the resources directory not being included in the final native build. So when I try running my app I receive this message.

Caused by: liquibase.exception.ChangeLogParseException: The file classpath:db/changelog/changelog.master.xml was not found in the configured search path:
    - Spring resources
More locations can be added with the 'searchPath' parameter.

I am using gradle multiproject build, and have a suspicion that it could be related, here is how my project structure looks like:

project structure

Here are the gradle configurations that relate to the native build

plugins {
    id 'java'
    id 'org.graalvm.buildtools.native' version '0.9.20'
    // springBootVersion = '3.1.0'
    id 'org.springframework.boot' version "${springBootVersion}"
    id 'io.spring.dependency-management' version '1.0.11.RELEASE'
    id 'processing.application.java-conventions'
    id 'idea'
}

graalvmNative {
    binaries {
        main {
            buildArgs.add('--initialize-at-build-time=org.apache.commons.logging.LogFactory,com.ctc.wstx.util.DefaultXmlSymbolTable,com.ctc.wstx.api.ReaderConfig,com.ctc.wstx.api.CommonConfig,com.ctc.wstx.stax.WstxInputFactory')
        }
    }
}

I am trying to create a native build using this command:

gradle application:nativeCompile

I would appreciate any help, thank you

  • In general, application resources are not compiled into the image by default (Spring resources probably are). You need to tell native-image to include them – peterz Jun 15 '23 at 13:52
  • Could you give me a hint on how to tell Graal VM to include specific files in the final build? – Dmytro Kostyushko Jun 19 '23 at 13:42
  • Sure, here's a [guide](https://www.graalvm.org/latest/reference-manual/native-image/dynamic-features/Resources/) on resource configuration. Also see [here](https://www.graalvm.org/latest/reference-manual/native-image/metadata/AutomaticMetadataCollection/) for how to automate the task – peterz Jun 20 '23 at 07:49

1 Answers1

0

Liquibase required little bit extra configuration and @josh-long written about it here The example is basically using graalvm mvn plugin to include resources into native build, find more details here

You can configure resource management with resource-config.json and reflect-config.json, below 2 jsons

reflect-config.json

[
  {
    "name": "com.sun.org.apache.xerces.internal.impl.dv.xs.ExtendedSchemaDVFactoryImpl",
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "com.sun.org.apache.xerces.internal.impl.dv.xs.SchemaDVFactoryImpl",
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl",
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "com.sun.xml.internal.stream.events.XMLEventFactoryImpl",
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.AbstractExtensibleObject",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.AbstractChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.AbstractSQLChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.ChangeFactory",
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.change.ColumnConfig",
    "allDeclaredFields": true,
    "allPublicMethods": true,
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.change.ConstraintsConfig",
    "allDeclaredFields": true
  },
  {
    "name": "liquibase.change.core.AbstractModifyDataChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.AddAutoIncrementChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.AddColumnChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.AddDefaultValueChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.AddForeignKeyConstraintChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.AddLookupTableChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.AddNotNullConstraintChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.AddPrimaryKeyChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.AddUniqueConstraintChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.AlterSequenceChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.CreateIndexChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.CreateProcedureChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.CreateSequenceChange",
    "allPublicMethods": true,
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.change.core.CreateTableChange",
    "allPublicMethods": true,
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.change.core.CreateViewChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.DeleteDataChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.DropAllForeignKeyConstraintsChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.DropColumnChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.DropDefaultValueChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.DropForeignKeyConstraintChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.DropIndexChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.DropNotNullConstraintChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.DropPrimaryKeyChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.DropProcedureChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.DropSequenceChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.DropTableChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.DropUniqueConstraintChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.DropViewChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.EmptyChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.ExecuteShellCommandChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.InsertDataChange",
    "allPublicMethods": true,
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.change.core.LoadDataChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.LoadUpdateDataChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.MergeColumnChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.ModifyDataTypeChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.OutputChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.RawSQLChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.RenameColumnChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.RenameSequenceChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.RenameTableChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.RenameViewChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.SQLFileChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.SetColumnRemarksChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.SetTableRemarksChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.StopChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.TagDatabaseChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.core.UpdateDataChange",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.change.custom.CustomChangeWrapper",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.changelog.StandardChangeLogHistoryService",
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.configuration.GlobalConfiguration",
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.configuration.HubConfiguration",
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.database.core.H2Database",
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.database.core.MariaDBDatabase",
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.database.core.MSSQLDatabase",
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.database.core.MySQLDatabase",
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.database.core.OracleDatabase",
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.database.core.PostgresDatabase",
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.database.jvm.JdbcConnection",
    "methods": [
      {
        "name": "getWrappedConnection",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.datatype.core.BigIntType",
    "allPublicMethods": true,
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.datatype.core.BlobType",
    "allPublicMethods": true,
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.datatype.core.BooleanType",
    "allPublicMethods": true,
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.datatype.core.CharType",
    "allPublicMethods": true,
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.datatype.core.ClobType",
    "allPublicMethods": true,
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.datatype.core.CurrencyType",
    "allPublicMethods": true,
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.datatype.core.DatabaseFunctionType",
    "allPublicMethods": true,
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.datatype.core.DateTimeType",
    "allPublicMethods": true,
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.datatype.core.DateType",
    "allPublicMethods": true,
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.datatype.core.DecimalType",
    "allPublicMethods": true,
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.datatype.core.DoubleType",
    "allPublicMethods": true,
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.datatype.core.FloatType",
    "allPublicMethods": true,
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.datatype.core.IntType",
    "allPublicMethods": true,
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.datatype.core.MediumIntType",
    "allPublicMethods": true,
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.datatype.core.NCharType",
    "allPublicMethods": true,
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.datatype.core.NumberType",
    "allPublicMethods": true,
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.datatype.core.NVarcharType",
    "allPublicMethods": true,
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.datatype.core.SmallIntType",
    "allPublicMethods": true,
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.datatype.core.TimestampType",
    "allPublicMethods": true,
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.datatype.core.TimeType",
    "allPublicMethods": true,
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.datatype.core.TinyIntType",
    "allPublicMethods": true,
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.datatype.core.UnknownType",
    "allPublicMethods": true,
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.datatype.core.UUIDType",
    "allPublicMethods": true,
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.datatype.core.VarcharType",
    "allPublicMethods": true,
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.datatype.core.XMLType",
    "allPublicMethods": true,
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.executor.ExecutorService",
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.executor.jvm.JdbcExecutor",
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.hub.HubServiceFactory",
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.license.LicenseServiceFactory",
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.lockservice.StandardLockService",
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.logging.core.LogServiceFactory",
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.parser.ChangeLogParserCofiguration",
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.plugin.AbstractPlugin",
    "allPublicMethods": true
  },
  {
    "name": "liquibase.serializer.AbstractLiquibaseSerializable",
    "allDeclaredFields": true
  },
  {
    "name": "liquibase.sql.visitor.AppendSqlVisitor",
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.sql.visitor.PrependSqlVisitor",
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.sql.visitor.RegExpReplaceSqlVisitor",
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.sql.visitor.ReplaceSqlVisitor",
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": []
      }
    ]
  },
  {
    "name": "liquibase.changelog.RanChangeSet",
    "allDeclaredMethods": true,
    "allDeclaredFields": true,
    "allDeclaredConstructors": true
  },
  {
    "name": "com.zaxxer.hikari.HikariConfig",
    "allDeclaredMethods": true,
    "allDeclaredFields": true,
    "allDeclaredConstructors": true
  },
  {
    "name": "java.util.concurrent.CopyOnWriteArrayList",
    "allDeclaredMethods": true,
    "allDeclaredFields": true,
    "allDeclaredConstructors": true
  },
  {
    "name": "java.sql.Statement[]",
    "allDeclaredMethods": true,
    "allDeclaredFields": true,
    "allDeclaredConstructors": true
  },
  {
    "name": "com.zaxxer.hikari.HikariDataSource",
    "allDeclaredMethods": true,
    "allDeclaredFields": true,
    "allDeclaredConstructors": true
  },
  {
    "name": "liquibase.configuration.LiquibaseConfiguration",
    "allDeclaredMethods": true,
    "allDeclaredFields": true,
    "allDeclaredConstructors": true
  },
  {
    "name": "com.zaxxer.hikari.util.ConcurrentBag.IConcurrentBagEntry[]",
    "allDeclaredMethods": true,
    "allDeclaredFields": true,
    "allDeclaredConstructors": true
  },
  {
    "name": "liquibase.change.core.LoadDataColumnConfig",
    "allDeclaredMethods": true,
    "allDeclaredFields": true,
    "allDeclaredConstructors": true
  }
]

resource-config.json

{
  "resources":[
    {"pattern":"\\Qliquibase.build.properties\\E"},
    {"pattern":"\\Qwww.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd\\E"},
    {"pattern":"\\Qwww.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.2.xsd\\E"},
    {"pattern":"\\Qwww.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.3.xsd\\E"},
    {"pattern":"\\Qwww.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.4.xsd\\E"},
    {"pattern":"\\Qwww.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd\\E"},
    {"pattern":"\\Qwww.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd\\E"},
    {"pattern":"\\Qwww.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.7.xsd\\E"},
    {"pattern":"\\Qwww.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.8.xsd\\E"},
    {"pattern":"\\Qwww.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.9.xsd\\E"},
    {"pattern":"\\Qwww.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.10.xsd\\E"},
    {"pattern":"\\Qwww.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.0.xsd\\E"},
    {"pattern":"\\Qwww.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd\\E"},
    {"pattern":"\\Qwww.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.2.xsd\\E"},
    {"pattern":"\\Qwww.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.3.xsd\\E"},
    {"pattern":"\\Qwww.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.4.xsd\\E"},
    {"pattern":"\\Qwww.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd\\E"},
    {"pattern":"\\Qwww.liquibase.org/xml/ns/pro/liquibase-pro-3.8.xsd\\E"},
    {"pattern":"\\Qwww.liquibase.org/xml/ns/pro/liquibase-pro-3.9.xsd\\E"},
    {"pattern":"\\Qwww.liquibase.org/xml/ns/pro/liquibase-pro-3.10.xsd\\E"},
    {"pattern":"\\Qwww.liquibase.org/xml/ns/pro/liquibase-pro-4.0.xsd\\E"},
    {"pattern":"\\Qwww.liquibase.org/xml/ns/pro/liquibase-pro-4.1.xsd\\E"},
    {"pattern":"\\Qwww.liquibase.org/xml/ns/pro/liquibase-pro-4.2.xsd\\E"},
    {"pattern":"\\Qwww.liquibase.org/xml/ns/pro/liquibase-pro-4.3.xsd\\E"},
    {"pattern":"\\Qwww.liquibase.org/xml/ns/pro/liquibase-pro-4.4.xsd\\E"}
  ],
  "bundles":[
    {"name":"com.sun.org.apache.xerces.internal.impl.xpath.regex.message"},
    {"name":"liquibase/i18n/liquibase-core"}
  ]
}

put those two files under src/main/resources and build.gradle also need extra configuration check this pom, probably soon liquibase will be fully supported without these but looks like this is the way for now.

ozkanpakdil
  • 3,199
  • 31
  • 48