Skip to content

Commit 50dc42c

Browse files
author
Christopher Frost
committed
Add support for JRebel
This commit adds support for using JRebel in an IDE to live edit an application running in Cloud Foundry. No service is required, only the presense of the rebel.xml and rebel-remote.xml files in the application that get's uploaded to Cloud Foundry. These files are often generated by the IDE's JRebel plugin. [#84050588]
1 parent 303bda3 commit 50dc42c

File tree

11 files changed

+184
-5
lines changed

11 files changed

+184
-5
lines changed

Diff for: README.md

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ To learn how to configure various properties of the buildpack, follow the "Confi
4343
* Standard Frameworks
4444
* [AppDynamics Agent](docs/framework-app_dynamics_agent.md) ([Configuration](docs/framework-app_dynamics_agent.md#configuration))
4545
* [Java Options](docs/framework-java_opts.md) ([Configuration](docs/framework-java_opts.md#configuration))
46+
* [JRebel Agent](docs/framework-jrebel_agent.md) ([Configuration](docs/framework-jrebel_agent.md#configuration))
4647
* [MariaDB JDBC](docs/framework-maria_db_jdbc.md) ([Configuration](docs/framework-maria_db_jdbc.md#configuration))
4748
* [New Relic Agent](docs/framework-new_relic_agent.md) ([Configuration](docs/framework-new_relic_agent.md#configuration))
4849
* [Play Framework Auto Reconfiguration](docs/framework-play_framework_auto_reconfiguration.md) ([Configuration](docs/framework-play_framework_auto_reconfiguration.md#configuration))

Diff for: config/components.yml

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ jres:
3434
frameworks:
3535
- "JavaBuildpack::Framework::AppDynamicsAgent"
3636
- "JavaBuildpack::Framework::JavaOpts"
37+
- "JavaBuildpack::Framework::JrebelAgent"
3738
- "JavaBuildpack::Framework::MariaDbJDBC"
3839
- "JavaBuildpack::Framework::NewRelicAgent"
3940
- "JavaBuildpack::Framework::PlayFrameworkAutoReconfiguration"

Diff for: config/jrebel_agent.yml

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Cloud Foundry Java Buildpack
2+
# Copyright (c) 2013 the original author or authors.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
# Configuration for the JRebel framework
17+
---
18+
version: 6.+
19+
repository_root: "{default.repository.root}/jrebel"

Diff for: docs/framework-jrebel_agent.md

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# JRebel Agent Framework
2+
The JRebel Agent Framework causes an application to be automatically configured to work with an IDE using [JRebel][].
3+
4+
<table>
5+
<tr>
6+
<td><strong>Detection Criterion</strong></td>
7+
<td>Existence of the `rebel.xml` and `rebel-remote.xml` files in either the root or `WEB-INF/classes` directory or the application.</td>
8+
</tr>
9+
<tr>
10+
<td><strong>Tags</strong></td>
11+
<td><tt>jrebel-agent=&lt;version&gt;</tt></td>
12+
</tr>
13+
</table>
14+
Tags are printed to standard output by the buildpack detect script
15+
16+
## Configuration
17+
For general information on configuring the buildpack, refer to [Configuration and Extension][].
18+
19+
The framework can be configured by modifying the [`config/jrebel_agent.yml`][] file in the buildpack fork. The framework uses the [`Repository` utility support][repositories] and so it supports the [version syntax][] defined there.
20+
21+
| Name | Description
22+
| ---- | -----------
23+
| `repository_root` | The URL of the JRebel repository index ([details][repositories]).
24+
| `version` | The version of Jrebel to use. Candidate versions can be found in [this listing][].
25+
26+
[Configuration and Extension]: ../README.md#configuration-and-extension
27+
[`config/jrebel_agent.yml`]: ../config/jrebel_agent.yml
28+
[JRebel]: http://zeroturnaround.com/software/jrebel/
29+
[repositories]: extending-repositories.md
30+
[this listing]: http://download.pivotal.io.s3.amazonaws.com/jrebel/index.yml
31+
[version syntax]: extending-repositories.md#version-syntax-and-ordering

Diff for: java-buildpack.iml

+2-2
Original file line numberDiff line numberDiff line change
@@ -281,13 +281,13 @@
281281
<orderEntry type="library" scope="PROVIDED" name="powerpack (v0.0.9, rbenv: 1.9.3-p551) [gem]" level="application" />
282282
<orderEntry type="library" scope="PROVIDED" name="rainbow (v2.0.0, rbenv: 1.9.3-p551) [gem]" level="application" />
283283
<orderEntry type="library" scope="PROVIDED" name="rake (v10.4.2, rbenv: 1.9.3-p551) [gem]" level="application" />
284-
<orderEntry type="library" scope="PROVIDED" name="redcarpet (v3.2.1, rbenv: 1.9.3-p551) [gem]" level="application" />
284+
<orderEntry type="library" scope="PROVIDED" name="redcarpet (v3.2.2, rbenv: 1.9.3-p551) [gem]" level="application" />
285285
<orderEntry type="library" scope="PROVIDED" name="rspec (v3.1.0, rbenv: 1.9.3-p551) [gem]" level="application" />
286286
<orderEntry type="library" scope="PROVIDED" name="rspec-core (v3.1.7, rbenv: 1.9.3-p551) [gem]" level="application" />
287287
<orderEntry type="library" scope="PROVIDED" name="rspec-expectations (v3.1.2, rbenv: 1.9.3-p551) [gem]" level="application" />
288288
<orderEntry type="library" scope="PROVIDED" name="rspec-mocks (v3.1.3, rbenv: 1.9.3-p551) [gem]" level="application" />
289289
<orderEntry type="library" scope="PROVIDED" name="rspec-support (v3.1.2, rbenv: 1.9.3-p551) [gem]" level="application" />
290-
<orderEntry type="library" scope="PROVIDED" name="rubocop (v0.27.1, rbenv: 1.9.3-p551) [gem]" level="application" />
290+
<orderEntry type="library" scope="PROVIDED" name="rubocop (v0.28.0, rbenv: 1.9.3-p551) [gem]" level="application" />
291291
<orderEntry type="library" scope="PROVIDED" name="rubocop-rspec (v1.2.1, rbenv: 1.9.3-p551) [gem]" level="application" />
292292
<orderEntry type="library" scope="PROVIDED" name="ruby-progressbar (v1.7.0, rbenv: 1.9.3-p551) [gem]" level="application" />
293293
<orderEntry type="library" scope="PROVIDED" name="rubyzip (v1.1.6, rbenv: 1.9.3-p551) [gem]" level="application" />

Diff for: lib/java_buildpack/component/java_opts.rb

+13-3
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ def initialize(droplet_root)
3333
@droplet_root = droplet_root
3434
end
3535

36-
# Adds a +javaagent+ entry to the +JAVA_OPTS+. Prepends +$PWD+ to the path (relative to the droplet root) to
36+
# Adds a +javaagent+ entry to the +JAVA_OPTS+. Prepends +$PWD+ to the path (relative to the droplet root) to
3737
# ensure that the path is always accurate.
3838
#
3939
# @param [Pathname] path the path to the +javaagent+ JAR
@@ -43,7 +43,17 @@ def add_javaagent(path)
4343
self
4444
end
4545

46-
# Adds a system property to the +JAVA_OPTS+. Ensures that the key is prepended with +-D+. If the value is a
46+
# Adds a +bootclasspath/p+ entry to the +JAVA_OPTS+. Prepends +$PWD+ to the path (relative to the droplet root) to
47+
# ensure that the path is always accurate.
48+
#
49+
# @param [Pathname] path the path to the +javaagent+ JAR
50+
# @return [JavaOpts] +self+ for chaining
51+
def add_bootclasspath_p(path)
52+
self << "-Xbootclasspath/p:#{qualify_path path}"
53+
self
54+
end
55+
56+
# Adds a system property to the +JAVA_OPTS+. Ensures that the key is prepended with +-D+. If the value is a
4757
# +Pathname+, then prepends +$PWD+ to the path (relative to the droplet root) to ensure that the path is always
4858
# accurate. Otherwise, uses the value as-is.
4959
#
@@ -55,7 +65,7 @@ def add_system_property(key, value)
5565
self
5666
end
5767

58-
# Adds an option to the +JAVA_OPTS+. Nothing is prepended to the key. If the value is a +Pathname+, then
68+
# Adds an option to the +JAVA_OPTS+. Nothing is prepended to the key. If the value is a +Pathname+, then
5969
# prepends +$PWD+ to the path (relative to the droplet root) to ensure that the path is always accurate.
6070
# Otherwise, uses the value as-is.
6171
#

Diff for: lib/java_buildpack/framework/jrebel_agent.rb

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Encoding: utf-8
2+
# Cloud Foundry Java Buildpack
3+
# Copyright 2013 the original author or authors.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
require 'fileutils'
18+
require 'java_buildpack/component/versioned_dependency_component'
19+
require 'java_buildpack/framework'
20+
21+
module JavaBuildpack
22+
module Framework
23+
24+
# Encapsulates the functionality for enabling zero-touch JRebel support.
25+
class JrebelAgent < JavaBuildpack::Component::VersionedDependencyComponent
26+
27+
# (see JavaBuildpack::Component::BaseComponent#compile)
28+
def compile
29+
download_zip false
30+
FileUtils.mv(download_location + 'jrebel.jar', @droplet.sandbox + jar_name)
31+
FileUtils.remove_dir(download_location, true)
32+
end
33+
34+
# (see JavaBuildpack::Component::BaseComponent#release)
35+
def release
36+
@droplet.java_opts
37+
.add_javaagent(@droplet.sandbox + jar_name)
38+
.add_bootclasspath_p(@droplet.sandbox + jar_name)
39+
.add_system_property('rebel.remoting_plugin', true)
40+
end
41+
42+
protected
43+
44+
# (see JavaBuildpack::Component::VersionedDependencyComponent#supports?)
45+
def supports?
46+
jrebel_configured?(@application.root) || jrebel_configured?(@application.root + 'WEB-INF/classes')
47+
end
48+
49+
private
50+
51+
def jrebel_configured?(root_path)
52+
(root_path + 'rebel.xml').exist? && (root_path + 'rebel-remote.xml').exist?
53+
end
54+
55+
def download_location
56+
@droplet.sandbox + 'jrebel'
57+
end
58+
59+
end
60+
61+
end
62+
end

Diff for: spec/fixtures/framework_jrebel_app/rebel-remote.xml

Whitespace-only changes.

Diff for: spec/fixtures/framework_jrebel_app/rebel.xml

Whitespace-only changes.

Diff for: spec/fixtures/stub-jrebel-archive.zip

480 Bytes
Binary file not shown.

Diff for: spec/java_buildpack/framework/jrebel_agent_spec.rb

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Encoding: utf-8
2+
# Cloud Foundry Java Buildpack
3+
# Copyright 2013 the original author or authors.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
require 'spec_helper'
18+
require 'component_helper'
19+
require 'java_buildpack/framework/jrebel_agent'
20+
21+
describe JavaBuildpack::Framework::JrebelAgent do
22+
include_context 'component_helper'
23+
24+
it 'does not detect without JRebel config files present' do
25+
expect(component.detect).to be_nil
26+
end
27+
28+
it 'detects with JRebel config files are present',
29+
app_fixture: 'framework_jrebel_app',
30+
cache_fixture: 'stub-jrebel-archive.zip' do
31+
expect(component.detect).to eq("jrebel-agent=#{version}")
32+
end
33+
34+
it 'downloads JRebel agent JAR',
35+
app_fixture: 'framework_jrebel_app',
36+
cache_fixture: 'stub-jrebel-archive.zip' do
37+
38+
component.compile
39+
40+
expect(sandbox + "jrebel_agent-#{version}.jar").to exist
41+
end
42+
43+
it 'updates JAVA_OPTS',
44+
app_fixture: 'framework_jrebel_app',
45+
cache_fixture: 'stub-jrebel-archive.zip' do
46+
allow(services).to receive(:find_service).and_return('credentials' => { 'licenseKey' => 'test-license-key' })
47+
48+
component.release
49+
50+
expect(java_opts).to include("-javaagent:$PWD/.java-buildpack/jrebel_agent/jrebel_agent-#{version}.jar")
51+
expect(java_opts).to include('-Drebel.remoting_plugin=true')
52+
expect(java_opts).to include("-Xbootclasspath/p:$PWD/.java-buildpack/jrebel_agent/jrebel_agent-#{version}.jar")
53+
end
54+
55+
end

0 commit comments

Comments
 (0)