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

Gretty 3.0.8+ is incompatible with Proguard 7.3.0 #277

Closed
boris-petrov opened this issue Nov 17, 2022 · 4 comments · Fixed by #279
Closed

Gretty 3.0.8+ is incompatible with Proguard 7.3.0 #277

boris-petrov opened this issue Nov 17, 2022 · 4 comments · Fixed by #279

Comments

@boris-petrov
Copy link
Member

build.gradle:

plugins {
	id 'org.gretty' version '3.0.8' apply false
}

settings.gradle:

include 'foo'

foo/build.gradle:

import proguard.gradle.ProGuardTask

buildscript {
	repositories {
		mavenCentral()
	}

	dependencies {
		classpath 'com.guardsquare:proguard-gradle:7.3.0'
	}
}

tasks.register('proguardFoo', ProGuardTask)

Running gradle foo:proguardFoo (with Gradle 7.5.1) on this fails with:

> Task :foo:proguardFoo FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':foo:proguardFoo'.
> Could not initialize class org.apache.logging.log4j.util.PropertiesUtil

Downgrading ProGuard to 7.2.2 or downgrading Gretty to 3.0.7 fixes the issue (i.e. there is another exception Index 0 out of bounds for length 0 which is normal however).

Initially I thought that this was because of the recent changes to classloader filtering (as I'm using Gretty 3.1.0 and was testing with it). However, the fact that Gretty 3.0.8 also doesn't work... is extremely strange. Also note that Gretty is not even applied here but without this line, it works correctly.

@f4lco, any ideas?

@f4lco
Copy link
Collaborator

f4lco commented Nov 19, 2022

This is really nasty. I have an unconfirmed hypothesis of what might have happened.

We upgraded dependencies: v3.0.7...gretty-gradle-plugin:gretty:v3.0.8

Therefore, we upgraded "org.springframework.boot:spring-boot-devtools", and by transitive dependency, "org.springframework.boot:spring-boot", from 2.0.2.RELEASE to 2.6.3.

Eventually, spring-boot adding SpringBootPropertySource in 2.5.2, a org.apache.logging.log4j.util.PropertySource, messes with Gradle's classloading.

There is no obvious version conflict, because spring-boot does not add another version of log4j-api on the classpath.

Nonetheless, the newer spring-boot puts

spring-boot-2.6.3.jar!/META-INF/services/org.apache.logging.log4j.util.PropertySource

on the class path, and ProGuards log4j initialization happily reads that. This is the point where my analysis gets fuzzy :D


Why do we have Spring Boot on Gretty's plugin classpath? Let' run gradle buildEnvironment:

classpath
\--- org.gretty:org.gretty.gradle.plugin:3.0.8
     \--- org.gretty:gretty:3.0.8
          +--- org.gretty:gretty-core:3.0.8
          |    +--- commons-cli:commons-cli:1.3.1
          |    +--- commons-configuration:commons-configuration:1.10
          |    |    +--- commons-lang:commons-lang:2.6
          |    |    \--- commons-logging:commons-logging:1.1.1
          |    +--- commons-io:commons-io:2.11.0
          |    +--- org.apache.commons:commons-lang3:3.3.2
          |    +--- org.bouncycastle:bcprov-jdk15on:1.60
          |    +--- org.springframework.boot:spring-boot-devtools:2.6.3
          |    |    +--- org.springframework.boot:spring-boot:2.6.3
          |    |    |    +--- org.springframework:spring-core:5.3.15
          |    |    |    |    \--- org.springframework:spring-jcl:5.3.15
          |    |    |    \--- org.springframework:spring-context:5.3.15
          |    |    |         +--- org.springframework:spring-aop:5.3.15
          |    |    |         |    +--- org.springframework:spring-beans:5.3.15
          |    |    |         |    |    \--- org.springframework:spring-core:5.3.15 (*)
          |    |    |         |    \--- org.springframework:spring-core:5.3.15 (*)
          |    |    |         +--- org.springframework:spring-beans:5.3.15 (*)
          |    |    |         +--- org.springframework:spring-core:5.3.15 (*)
          |    |    |         \--- org.springframework:spring-expression:5.3.15
          |    |    |              \--- org.springframework:spring-core:5.3.15 (*)
          |    |    \--- org.springframework.boot:spring-boot-autoconfigure:2.6.3
          |    |         \--- org.springframework.boot:spring-boot:2.6.3 (*)
          |    \--- org.gretty:gretty-common:3.0.8
          |         \--- org.slf4j:slf4j-api:1.7.36
          +--- org.springframework.boot:spring-boot-loader-tools:2.6.3
          |    +--- org.apache.commons:commons-compress:1.21
          |    \--- org.springframework:spring-core:5.3.15 (*)
          \--- org.eclipse.jetty:jetty-util:8.1.22.v20160922

This is a really massive dependency tree for supporting only a single feature on Gretty, namely the LiveReload server, which can reload the browser when the server code changes.

If it was for me, I'd just drop support for LiveReload server from Gretty, and see if the incompatibility, caused by the dependency problem, persists.
Eventually, nobody is using LiveReload any more. I'd base this assumption on the fact that the most recent commits to LiveReload repositories are from 6 to 7 years ago, and the website appears dead for more than one year (according to GitHub issues).

Another option would be to copy the 5 classes we actually use from spring-boot-devtools over to Gretty.

In both approaches, Gretty would do fine without entire Spring (Boot) on the plugin's classpath.

I'm happy to hear an opinion on this @boris-petrov!

@boris-petrov
Copy link
Member Author

@f4lco thanks for the detailed analysis!

I'm still not sure what exactly the problem is but I guess your reasoning is sound and the issue follows from what you say.

I don't think LiveReload is abandoned - this issue for example suggests that they want to continue supporting it. But I'm totally fine with removing it though. I'm not using it so I don't mind. 😄 Not sure if that's the right way... but we could try and see if anybody complains. 😄

Should I take a shot at removing it?

@f4lco
Copy link
Collaborator

f4lco commented Nov 19, 2022

I'm unsure @boris-petrov. How many features can we steal from Gretty...?
I mean, I previously dropped support for stuff, say Logback, out of true necessity, and for greater good, say, support of Jetty 10. But in this instance... if Spring Boot is continuing support, maybe it's to early to declare it dead. We could produce a proper implementation, which is truly opt-in, and perhaps useful for other purposes, too. On the other hand, well, it is work 😂

It's been a mistake to hard-wire Spring into Gretty's tasks. That is why a simple dependency exclusion will not fix your issue, sadly:

* What went wrong:
A problem occurred configuring project ':bar'.
> Could not create task ':bar:farmBeforeIntegrationTest'.
   > Could not create task of type 'FarmBeforeIntegrationTestTask'.
      > Could not generate a decorated class for type FarmBeforeIntegrationTestTask.
         > org/springframework/boot/devtools/autoconfigure/OptionalLiveReloadServer

I do not have a strong opinion on this, it's either removal or rework... otherwise the dependency setup as-is will cause problems down the road, not only with ProGuard.

boris-petrov added a commit that referenced this issue Nov 30, 2022
As that causes conflicts in user projects:
#277
@boris-petrov boris-petrov linked a pull request Nov 30, 2022 that will close this issue
boris-petrov added a commit that referenced this issue Dec 20, 2022
As that causes conflicts in user projects:
#277
@boris-petrov
Copy link
Member Author

This issue has been resolved as of Gretty 3.1.1! Thanks @f4lco for the insight and help!

boris-petrov added a commit that referenced this issue Jan 6, 2023
As that causes conflicts in user projects:
#277
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants