diff --git a/README.md b/README.md index e563ea745d..e562ea1a34 100644 --- a/README.md +++ b/README.md @@ -126,6 +126,7 @@ The buildpack supports extension through the use of Git repository forking. The * [Google Stackdriver Profiler](docs/framework-google_stackdriver_profiler.md) ([Configuration](docs/framework-google_stackdriver_profiler.md#configuration)) * [Introscope Agent](docs/framework-introscope_agent.md) ([Configuration](docs/framework-introscope_agent.md#configuration)) * [JaCoCo Agent](docs/framework-jacoco_agent.md) ([Configuration](docs/framework-jacoco_agent.md#configuration)) + * [Java CfEnv](docs/framework-java-cfenv.md) ([Configuration](docs/framework-java-cfenv.md#configuration)) * [Java Memory Assistant](docs/framework-java_memory_assistant.md) ([Configuration](docs/framework-java_memory_assistant.md#configuration)) * [Java Options](docs/framework-java_opts.md) ([Configuration](docs/framework-java_opts.md#configuration)) * [JProfiler Profiler](docs/framework-jprofiler_profiler.md) ([Configuration](docs/framework-jprofiler_profiler.md#configuration)) diff --git a/config/components.yml b/config/components.yml index 41d7bc1b73..79a60156fd 100644 --- a/config/components.yml +++ b/config/components.yml @@ -54,10 +54,11 @@ frameworks: - "JavaBuildpack::Framework::Debug" - "JavaBuildpack::Framework::DynatraceOneAgent" - "JavaBuildpack::Framework::ElasticApmAgent" -# - "JavaBuildpack::Framework::GoogleStackdriverDebugger" +# - "JavaBuildpack::Framework::GoogleStackdriverDebugger" - "JavaBuildpack::Framework::GoogleStackdriverProfiler" - "JavaBuildpack::Framework::IntroscopeAgent" - "JavaBuildpack::Framework::JacocoAgent" + - "JavaBuildpack::Framework::JavaCfEnv" - "JavaBuildpack::Framework::JavaMemoryAssistant" - "JavaBuildpack::Framework::Jmx" - "JavaBuildpack::Framework::JprofilerProfiler" diff --git a/config/java_cf_env.yml b/config/java_cf_env.yml new file mode 100644 index 0000000000..a021138ff7 --- /dev/null +++ b/config/java_cf_env.yml @@ -0,0 +1,22 @@ +# Cloud Foundry Java Buildpack +# Copyright 2013-2023 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Configuration for the Java CfEnv framework. +# See https://github.com/pivotal-cf/java-cfenv for library information + +--- +version: 3.+ +repository_root: "{default.repository.root}/java-cfenv" +enabled: true diff --git a/config/packaging.yml b/config/packaging.yml index aed29fdc22..8818f0c517 100644 --- a/config/packaging.yml +++ b/config/packaging.yml @@ -82,6 +82,10 @@ jacoco_agent: name: JaCoCo Agent release_notes: '[Release Notes](https://github.com/jacoco/jacoco/releases)' +java_cf_env: + name: Java CFEnv + release_notes: '[Release Notes](https://github.com/pivotal-cf/java-cfenv/releases)' + jprofiler_profiler: name: JProfiler Profiler release_notes: '[ChangeLog](https://www.ej-technologies.com/download/jprofiler/changelog.html)' diff --git a/docs/framework-java-cfenv.md b/docs/framework-java-cfenv.md new file mode 100644 index 0000000000..1e1fe474a7 --- /dev/null +++ b/docs/framework-java-cfenv.md @@ -0,0 +1,19 @@ +# Java CfEnv Framework +The Java CfEnv Framework provides the `java-cfenv` library for Spring Boot 3+ applications. This library sets various Spring Boot properties by parsing CloudFoundry variables such as `VCAP_SERVICES`, allowing Spring Boot's autoconfiguration to kick in. + +This is the recommended replacement for Spring AutoReconfiguration library which is deprecated. See the `java-cfenv` repostitory for more detail. + +It also sets the 'cloud' profile for Spring Boot applications, as the Spring AutoReconfiguration framework did. + + + + + + + + + + + +
Detection CriterionExistence of a spring-boot-3*.jar file in the application directory or a `Spring-Boot-Version: 3.*` manifest entryNo existing `java-cfenv` library found
Tagsjava-cf-env=<version>
+Tags are printed to standard output by the buildpack detect script diff --git a/lib/java_buildpack/framework/java_cf_env.rb b/lib/java_buildpack/framework/java_cf_env.rb new file mode 100644 index 0000000000..3b3644a040 --- /dev/null +++ b/lib/java_buildpack/framework/java_cf_env.rb @@ -0,0 +1,66 @@ +# frozen_string_literal: true + +# Cloud Foundry Java Buildpack +# Copyright 2013-2020 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +require 'java_buildpack/component/versioned_dependency_component' +require 'java_buildpack/framework' +require 'java_buildpack/util/spring_boot_utils' + +module JavaBuildpack + module Framework + + # Encapsulates the detect, compile, and release functionality for enabling cloud auto-reconfiguration in Spring + # applications. + class JavaCfEnv < JavaBuildpack::Component::VersionedDependencyComponent + include JavaBuildpack::Util + + def initialize(context) + @spring_boot_utils = JavaBuildpack::Util::SpringBootUtils.new + super(context) + end + + # (see JavaBuildpack::Component::BaseComponent#compile) + def compile + download_jar + @droplet.additional_libraries << (@droplet.sandbox + jar_name) + end + + # (see JavaBuildpack::Component::BaseComponent#release) + def release + @droplet.additional_libraries << (@droplet.sandbox + jar_name) + end + + protected + + # (see JavaBuildpack::Component::VersionedDependencyComponent#supports?) + def supports? + @configuration['enabled'] && spring_boot_3? && !java_cfenv? + end + + private + + def spring_boot_3? + @spring_boot_utils.is?(@application) && Gem::Version.new((@spring_boot_utils.version @application)).release >= + Gem::Version.new('3.0.0') + end + + def java_cfenv? + (@droplet.root + '**/*java-cfenv*.jar').glob.any? + end + + end + end +end diff --git a/lib/java_buildpack/framework/spring_auto_reconfiguration.rb b/lib/java_buildpack/framework/spring_auto_reconfiguration.rb index 80b20ca027..f53646e240 100644 --- a/lib/java_buildpack/framework/spring_auto_reconfiguration.rb +++ b/lib/java_buildpack/framework/spring_auto_reconfiguration.rb @@ -33,6 +33,7 @@ def initialize(context) # (see JavaBuildpack::Component::BaseComponent#compile) def compile log_warning_scc_manual if spring_cloud_connectors? + return if java_cf_env_framework? download_jar @droplet.additional_libraries << (@droplet.sandbox + jar_name) @@ -42,6 +43,8 @@ def compile # (see JavaBuildpack::Component::BaseComponent#release) def release + return if java_cf_env_framework? + @droplet.additional_libraries << (@droplet.sandbox + jar_name) end @@ -59,7 +62,13 @@ def spring? end def java_cfenv? - (@droplet.root + '**/*java-cfenv*.jar').glob.any? + (@droplet.root + '**/*java-cfenv*.jar').glob.any? || java_cf_env_framework? + end + + def java_cf_env_framework? + @droplet.additional_libraries.any? do |additional_library| + additional_library.instance_variable_get(:@pathname).fnmatch?('*java_cf_env*.jar') + end end def spring_cloud_connectors? diff --git a/spec/fixtures/framework_java_cf_boot_2/META-INF/MANIFEST.MF b/spec/fixtures/framework_java_cf_boot_2/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..ce0077f4ce --- /dev/null +++ b/spec/fixtures/framework_java_cf_boot_2/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Spring-Boot-Lib: manifest-lib-value/ +Main-Class: org.springframework.boot.loader.JarLauncher +Spring-Boot-Version: 2.1.0.RELEASE diff --git a/spec/fixtures/framework_java_cf_boot_2/WEB-INF/lib/spring-boot-1.0.0.RELEASE.jar b/spec/fixtures/framework_java_cf_boot_2/WEB-INF/lib/spring-boot-1.0.0.RELEASE.jar new file mode 100644 index 0000000000..e69de29bb2 diff --git a/spec/fixtures/framework_java_cf_boot_3/META-INF/MANIFEST.MF b/spec/fixtures/framework_java_cf_boot_3/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..a64827339d --- /dev/null +++ b/spec/fixtures/framework_java_cf_boot_3/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Spring-Boot-Lib: manifest-lib-value/ +Main-Class: org.springframework.boot.loader.JarLauncher +Spring-Boot-Version: 3.0.0.M1 diff --git a/spec/fixtures/framework_java_cf_boot_3/WEB-INF/lib/spring-boot-3.0.0.M1.jar b/spec/fixtures/framework_java_cf_boot_3/WEB-INF/lib/spring-boot-3.0.0.M1.jar new file mode 100644 index 0000000000..e69de29bb2 diff --git a/spec/fixtures/framework_java_cf_exists/META-INF/MANIFEST.MF b/spec/fixtures/framework_java_cf_exists/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..47eb0c27e7 --- /dev/null +++ b/spec/fixtures/framework_java_cf_exists/META-INF/MANIFEST.MF @@ -0,0 +1,4 @@ +Spring-Boot-Lib: manifest-lib-value/ +Spring-Boot-Version: 3.2.5.RELEASE +Main-Class: org.springframework.boot.loader.JarLauncher + diff --git a/spec/fixtures/framework_java_cf_exists/WEB-INF/lib/java-cfenv-2.1.2.RELEASE.jar b/spec/fixtures/framework_java_cf_exists/WEB-INF/lib/java-cfenv-2.1.2.RELEASE.jar new file mode 100644 index 0000000000..e69de29bb2 diff --git a/spec/fixtures/framework_java_cf_exists/WEB-INF/lib/java-cfenv-boot-2.1.2.RELEASE.jar b/spec/fixtures/framework_java_cf_exists/WEB-INF/lib/java-cfenv-boot-2.1.2.RELEASE.jar new file mode 100644 index 0000000000..e69de29bb2 diff --git a/spec/fixtures/framework_java_cf_exists/WEB-INF/lib/java-cfenv-jdbc-2.1.2.RELEASE.jar b/spec/fixtures/framework_java_cf_exists/WEB-INF/lib/java-cfenv-jdbc-2.1.2.RELEASE.jar new file mode 100644 index 0000000000..e69de29bb2 diff --git a/spec/fixtures/framework_java_cf_exists/WEB-INF/lib/spring-boot-3.2.3.RELEASE.jar b/spec/fixtures/framework_java_cf_exists/WEB-INF/lib/spring-boot-3.2.3.RELEASE.jar new file mode 100644 index 0000000000..e69de29bb2 diff --git a/spec/fixtures/stub-java-cfenv.jar b/spec/fixtures/stub-java-cfenv.jar new file mode 100644 index 0000000000..0878c3ccb5 Binary files /dev/null and b/spec/fixtures/stub-java-cfenv.jar differ diff --git a/spec/java_buildpack/framework/java_cfenv_spec.rb b/spec/java_buildpack/framework/java_cfenv_spec.rb new file mode 100644 index 0000000000..bfd67e7729 --- /dev/null +++ b/spec/java_buildpack/framework/java_cfenv_spec.rb @@ -0,0 +1,76 @@ +# frozen_string_literal: true + +# Cloud Foundry Java Buildpack +# Copyright 2013-2020 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +require 'spec_helper' +require 'component_helper' +require 'logging_helper' +require 'java_buildpack/framework/java_cf_env' + +describe JavaBuildpack::Framework::JavaCfEnv do + include_context 'with component help' + include_context 'with console help' + include_context 'with logging help' + + let(:configuration) { { 'enabled' => true } } + + it 'detects with Spring Boot 3 JAR', + app_fixture: 'framework_java_cf_boot_3' do + + expect(component.detect).to eq("java-cf-env=#{version}") + end + + it 'does not detect with Spring Boot < 3', + app_fixture: 'framework_java_cf_boot_2' do + + expect(component.detect).to be_nil + end + + it 'does not detect with Spring Boot 3 & java-cfenv present', + app_fixture: 'framework_java_cf_exists' do + + expect(component.detect).to be_nil + end + + context do + let(:configuration) { { 'enabled' => false } } + + it 'does not detect if disabled', + app_fixture: 'framework_java_cf_boot_3' do + + expect(component.detect).to be_nil + end + end + + it 'downloads additional libraries', + app_fixture: 'framework_java_cf_boot_3', + cache_fixture: 'stub-java-cfenv.jar' do + + component.compile + + expect(sandbox + "java_cf_env-#{version}.jar").to exist + end + + it 'adds to additional libraries', + app_fixture: 'framework_java_cf_boot_3', + cache_fixture: 'stub-java-cfenv.jar' do + + component.release + + expect(additional_libraries).to include(sandbox + "java_cf_env-#{version}.jar") + end + +end diff --git a/spec/java_buildpack/framework/spring_auto_reconfiguration_spec.rb b/spec/java_buildpack/framework/spring_auto_reconfiguration_spec.rb index d3f5cec59c..17a2946b04 100644 --- a/spec/java_buildpack/framework/spring_auto_reconfiguration_spec.rb +++ b/spec/java_buildpack/framework/spring_auto_reconfiguration_spec.rb @@ -39,7 +39,7 @@ expect(component.detect).to eq("spring-auto-reconfiguration=#{version}") end - it 'does not detect with Spring JAR and java-cfenv', + it 'does not detect with Spring JAR and user java-cfenv', app_fixture: 'framework_auto_reconfiguration_java_cfenv' do expect(component.detect).to be_nil @@ -104,4 +104,21 @@ expect(additional_libraries).to include(sandbox + "spring_auto_reconfiguration-#{version}.jar") end + context('when java-cfenv injects its lib') do + + before do + additional_libraries.insert 0, additional_libs_directory + 'java_cf_env.jar' + end + + after do + additional_libraries.delete additional_libs_directory + 'java_cf_env.jar' + end + + it 'does not detect with Spring JAR and injected cfenv', + app_fixture: 'framework_auto_reconfiguration_servlet_3' do + + expect(component.detect).to be_nil + end + + end end