Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

flyway-core depends on gson: fails if not present #3672

Open
selliera opened this issue May 15, 2023 · 10 comments
Open

flyway-core depends on gson: fails if not present #3672

selliera opened this issue May 15, 2023 · 10 comments

Comments

@selliera
Copy link

selliera commented May 15, 2023

Which version and edition of Flyway are you using?

Version 9.17.0

If this is not the latest version, can you reproduce the issue with the latest one as well? (Many bugs are fixed in newer releases and upgrading will often resolve the issue)

Yes

Which client are you using? (Command-line, Java API, Maven plugin, Gradle plugin)

flyway-core java API

Which database are you using? (Type & version)

any

Which operating system are you using?

linux

What did you do? (Please include the content causing the issue, any relevant configuration settings, the SQL statement(s) that failed (if any), and the command you ran)

Use flyway-core embedded in a tomcat service. Gson is not included in the application, which was fine until 9.17.0.

What did you expect to see?

Expected flyway-core to work embedded in the server, even if Gson is not present. Flyway itself has no reasons to impose a json marshaller or another.

What did you see instead?

Runtime failure, with a message like:

java.util.ServiceConfigurationError: org.flywaydb.core.extensibility.Plugin: org.flywaydb.core.internal.reports.json.InfoResultDeserializer Unable to get public no-arg constructor

Another plugin depends on gson here: org.flywaydb.core.internal.reports.json.MigrateResultDeserializer.

I see no easy way to disable the org.flywaydb.core.internal.reports.json.InfoResultDeserializer from flyway-core, but that could be an option.
Previous to commit 60a5ad1 Gson was a dependency for the cli, but not for flyway-core.
Removing the two problematic plugins from the flyway-core\src\main\resources\META-INF\services\org.flywaydb.core.extensibility.Plugin file, I can again use flyway-core api in my application without embedding the Gson library.

@Barry-RG
Copy link
Contributor

Could you please provide us with a minimal reproduction? Please include the Flyway dependencies you are importing as well as a code snippet of your Flyway usage where possible.

@selliera
Copy link
Author

Hello,

I'm embedding flyway-core-9.14.1 and flyway-mysql-9.14.1 jars in a tomcat application.
I'm embedding no further dependencies (build system is not using maven)
What I do is define an @startup class, in those @PostConstruct I do use the flyway migrate call, to install or upgrade the database schema.

Something like:

@Startup
@Singleton(name="DatabaseInit")
@TransactionManagement(TransactionManagementType.BEAN)
public class DatabaseInit {

  @Resource(name = "mydb", type = javax.sql.DataSource.class)
  private DataSource db;

  @PostConstruct
  private void onStartup() {
    boolean cleanDisabled = Boolean.parseBoolean(System.getProperty("flyway.cleanDisabled", "true"));

    Flyway flyway = new Flyway(new FluentConfiguration()
        .cleanDisabled(cleanDisabled)
        .locations("classpath:com/mydb/db/migration")
        .dataSource(db)
    	);
    try {
      MigrateResult migrateResult = flyway.migrate();
      logger.info("{} migrations from {} to {}: {}",
          migrateResult.migrationsExecuted,
          migrateResult.initialSchemaVersion,
          migrateResult.targetSchemaVersion,
          migrateResult.success);
    } catch (FlywayException e) {
      logger.error("database migration failed", e);
    }
  }
}

This used to not require any more dependencies. I see that in the pom the dependency jackson-dataformat-toml was not marked as optional, but it did not cause problems.
Now with 9.17.0, both Gson and commons-text are not marked as optional. But they should not be required for all workloads, so it would be better to be able to not require them.

@Barry-RG
Copy link
Contributor

Are you using a build tool like Maven or adding dependencies directly to the classpath?

@selliera
Copy link
Author

I'm using tools that do not rely on maven poms, but let me control the classpath. So basically manage the classpath manually, as well as the content of the war I deploy to tomcat.
That is why we didn't pick Gson automatically: we want to control the content of the war, for several reasons:

  • performance: each jar, even barely used, has its cost, e.g. on tomcat startup time
  • legal reasons: need to make sure the licenses of everything we deploy are fine, and everything declared correctly

@Barry-RG
Copy link
Contributor

Thank you for your additional information. I will take this back to the team as these dependencies are required for new functionality put into Flyway 9.17.0. However, the information above raises some thoughts which we need to consider moving forward. Thank you.

@CalebCintary
Copy link

Bumping plugin version from 9.16.0 to 9.19.1 solves the problem

@reitzmichnicht
Copy link

It would be great if flyway-core would not depend on new dependencies that are only used for optional features. Reporting is in my opinion not part of core and should be an extra dependency.

@jochenwalz
Copy link

Please note that for OSGi, that is a blocker, because flyway-core doesn't import com.google.gson (see Import-Package in MANIFEST.MF) but obviously tries to use it. Even when the gson bundle is correctly deployed and the package com.google.gson exported, flyway doesn't work.

@selliera
Copy link
Author

Hello,

I reproduced the issue with flyway 10.11.0: flyway-core explicitly depends on gson

java.util.ServiceConfigurationError: org.flywaydb.core.extensibility.Plugin: org.flywaydb.core.internal.reports.json.InfoResultDeserializer Unable to get public no-arg constructor
at java.base/java.util.ServiceLoader.fail(ServiceLoader.java:594)
at java.base/java.util.ServiceLoader.getConstructor(ServiceLoader.java:687)
at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNextService(ServiceLoader.java:1259)
at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNext(ServiceLoader.java:1292)
at java.base/java.util.ServiceLoader$2.hasNext(ServiceLoader.java:1328)
at java.base/java.util.ServiceLoader$3.hasNext(ServiceLoader.java:1412)
at org.flywaydb.core.internal.plugin.PluginRegister.registerPlugins(PluginRegister.java:83)
at org.flywaydb.core.internal.plugin.PluginRegister.getPlugins(PluginRegister.java:73)
at org.flywaydb.core.internal.plugin.PluginRegister.getCopy(PluginRegister.java:96)
at org.flywaydb.core.api.configuration.ClassicConfiguration.configure(ClassicConfiguration.java:1344)
at org.flywaydb.core.api.configuration.ClassicConfiguration.(ClassicConfiguration.java:257)
at org.flywaydb.core.Flyway.(Flyway.java:112)
at org.flywaydb.core.api.configuration.FluentConfiguration.load(FluentConfiguration.java:61)
at com.ds.ven.flyway.tests.TestFlyway.testFlyway(TestFlyway.java:14)
... 38 trimmed
Caused by: java.lang.NoClassDefFoundError: com.google.gson.JsonElement
at java.base/java.lang.J9VMInternals.prepareClassImpl(Native Method)
at java.base/java.lang.J9VMInternals.prepare(J9VMInternals.java:361)
at java.base/java.lang.Class.getConstructor(Class.java:689)
at java.base/java.util.ServiceLoader$1.run(ServiceLoader.java:674)
at java.base/java.util.ServiceLoader$1.run(ServiceLoader.java:671)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:748)
at java.base/java.util.ServiceLoader.getConstructor(ServiceLoader.java:682)
... 51 more
Caused by: java.lang.ClassNotFoundException: com.google.gson.JsonElement
at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:574)
at java.base/java.lang.ClassLoader.loadClassHelper(ClassLoader.java:1196)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:1111)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:1094)
... 58 more

@selliera
Copy link
Author

And a new dependency on fasterxml jackson appeared too:
java.lang.NoClassDefFoundError: com.fasterxml.jackson.databind.ObjectMapper
at org.flywaydb.core.extensibility.ConfigurationExtension.copy(ConfigurationExtension.java:36)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:522)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:512)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants