salesforce / rules_spring

Bazel rule for building Spring Boot apps as a deployable jar
BSD 3-Clause "New" or "Revised" License
221 stars 49 forks source link

Add first class support for add-opens and add-exports for launching via bazel run #175

Closed plaird closed 4 months ago

plaird commented 6 months ago

As users start upgrading to JDK17 and beyond, they will sometimes be impacted by stricter Java modularization enforcement.

[main] WARN  c.e.SomeImpl - [MAM] jvmm Failed to access compilationMxBean
java.lang.IllegalAccessError: class com.example.SomeImpl (in unnamed module @0x7e9a5fbe) cannot access 
  class sun.management.ManagementFactoryHelper (in module java.management) because module 
  java.management does not export sun.management to unnamed module @0x7e9a5fbe

The JDK has two mechanisms for loosening those restrictions described here:

Current Solutions

When launching a springboot target using bazel run, you can currently utilize the workarounds in two ways:

  1. Defined in the shell:

    export JAVA_OPTS="--add-opens=java.management/sun.management=ALL-UNNAMED" 
    bazel run //examples/helloworld
  2. Defined in the BUILD file:

//examples/helloworld/BUILD

springboot(
    name = "helloworld",
    boot_app_class = "com.examples.Hello",
    java_library = ":base_lib",
    bazelrun_jvm_flags = "--add-opens=java.management/sun.management=ALL-UNNAMED",
)

Proposed Enhancements

This issue proposes first class support of these workarounds in the BUILD file. This will be cleaner, and will also allow easy reuse across many springboot rules in a monorepo.

//common/jdk.bzl

common_addopens =  ["java.management/sun.management=ALL-UNNAMED"],

//examples/helloworld/BUILD

springboot(
    name = "helloworld",
    boot_app_class = "com.examples.Hello",
    java_library = ":base_lib",
    bazelrun_addopens = common_addopens,
)

add-exports would be handled in the same way as its own attribute.

Downstream Considerations

Consider also that many teams will have a macro (not included in rules_spring) that packages up their springboot executable jar into an OCI/Docker image. That macro will want to have similar support such that the launch of the service within the container will also use the opens/exports. Having these lists defined as variables will help with that.

java_docker_image(
  name = "docker_image",
  srcs = [":helloworld.jar"],
  addopens = common_addopens,
)