Skip to content

Commit f00b00c

Browse files
committed
Redis-based Session Replication
Previously, all Tomcat Sessions existed only in memory. In the case that a specific instance failed, the data in the Sessions hosted by that instance would be lost. In some circumstances this isn't ideal, so Sessions should be replicated to an external repository. This change adds support for persisting Sessions to a Redis instance. It does this by using the RedisStore Tomcat PersistentManager Store implementation. As part of this effort the Tomcat container was refactored (it was already too complicated) and a ModularComponent base type was created. The ModularComponent allows enables a component to be composed of multiple "sub-components" and coordinates the component lifecycle across all of them. [#66942528]
1 parent 46989e8 commit f00b00c

40 files changed

Lines changed: 1261 additions & 442 deletions

.idea/dictionaries/bhale.xml

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/runConfigurations/Without_Integration_Tests.xml

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Gemfile.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ GEM
1111
diff-lcs (1.2.5)
1212
docile (1.1.3)
1313
json (1.8.1)
14-
multi_json (1.8.4)
15-
parser (2.1.5)
14+
multi_json (1.9.0)
15+
parser (2.1.7)
1616
ast (~> 1.1)
1717
slop (~> 3.4, >= 3.4.5)
1818
powerpack (0.0.9)

config/tomcat.yml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,18 @@
1515

1616
# Configuration for the Tomcat container
1717
---
18-
version: 7.0.+
19-
repository_root: "{default.repository.root}/tomcat"
18+
tomcat:
19+
version: 7.0.+
20+
repository_root: "{default.repository.root}/tomcat"
2021
lifecycle_support:
2122
version: 2.+
2223
repository_root: "{default.repository.root}/tomcat-lifecycle-support"
2324
logging_support:
2425
version: 2.+
2526
repository_root: "{default.repository.root}/tomcat-logging-support"
27+
redis_store:
28+
version: 1.+
29+
repository_root: "{default.repository.root}/redis-store"
30+
database: 0
31+
timeout: 2000
32+
connection_pool_size: 2

docs/container-tomcat.md

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ The Tomcat Container allows servlet 2 and 3 web applications to be run. These a
77
</tr>
88
<tr>
99
<td><strong>Tags</strong></td>
10-
<td><tt>tomcat=&lang;version&rang;</tt>, <tt>tomcat-buildpack-support=&lang;version&rang;</tt></td>
10+
<td><tt>tomcat-instance=&lang;version&rang;</tt>, <tt>tomcat-lifecycle-support=&lang;version&rang;</tt>, <tt>tomcat-logging-support=&lang;version&rang;</tt> <tt>tomcat-redis-store=&lang;version&rang;</tt> <i>(optional)</i></td>
1111
</tr>
1212
</table>
1313
Tags are printed to standard output by the buildpack detect script
@@ -21,8 +21,24 @@ The container can be configured by modifying the [`config/tomcat.yml`][] file.
2121

2222
| Name | Description
2323
| ---- | -----------
24-
| `repository_root` | The URL of the Tomcat repository index ([details][repositories]).
25-
| `version` | The version of Tomcat to use. Candidate versions can be found in [this listing][].
24+
| `tomcat.repository_root` | The URL of the Tomcat repository index ([details][repositories]).
25+
| `tomcat.version` | The version of Tomcat to use. Candidate versions can be found in [this listing](http://download.pivotal.io.s3.amazonaws.com/tomcat/index.yml).
26+
| `lifecycle_support.repository_root` | The URL of the Tomcat Lifecycle Support repository index ([details][repositories]).
27+
| `lifecycle_support.version` | The version of Tomcat Lifecycle Support to use. Candidate versions can be found in [this listing](http://download.pivotal.io.s3.amazonaws.com/tomcat-lifecycle-support/index.yml).
28+
| `logging_support.repository_root` | The URL of the Tomcat Logging Support repository index ([details][repositories]).
29+
| `logging_support.version` | The version of Tomcat Logging Support to use. Candidate versions can be found in [this listing](http://download.pivotal.io.s3.amazonaws.com/tomcat-logging-support/index.yml).
30+
| `redis_store.repository_root` | The URL of the Redis Store repository index ([details][repositories]).
31+
| `redis_store.version` | The version of Redis Store to use. Candidate versions can be found in [this listing](http://download.pivotal.io.s3.amazonaws.com/redis-store/index.yml).
32+
| `redis_store.database` | The Redis database to connect to.
33+
| `redis_store.timeout` | The Redis connection timeout (in milliseconds).
34+
| `redis_store.connection_pool_size` | The Redis connection pool size. Note that this is per-instance, not per-application.
35+
36+
## Session Replication
37+
By default, the Tomcat instance is configured to store all Sessions and their data in memory. Under certain cirmcumstances it my be appropriate to persist the Sessions and their data to a repository. When this is the case (small amounts of data that should survive the failure of any individual instance), the buildpack can automatically configure Tomcat to do so.
38+
39+
### Redis
40+
To enable Redis-based session replication, simply bind a Redis service containing a name, label, or tag that has `session-replication` as a substring.
41+
2642

2743
## Supporting Functionality
2844
Additional supporting functionality can be found in the [`java-buildpack-support`][] Git repository.
@@ -33,5 +49,4 @@ Additional supporting functionality can be found in the [`java-buildpack-support
3349
[repositories]: extending-repositories.md
3450
[Spring profiles]:http://blog.springsource.com/2011/02/14/spring-3-1-m1-introducing-profile/
3551
[`SPRING_PROFILES_ACTIVE`]: http://docs.spring.io/spring/docs/4.0.0.RELEASE/javadoc-api/org/springframework/core/env/AbstractEnvironment.html#ACTIVE_PROFILES_PROPERTY_NAME
36-
[this listing]: http://download.pivotal.io.s3.amazonaws.com/tomcat/index.yml
3752
[version syntax]: extending-repositories.md#version-syntax-and-ordering
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# `JavaBuildpack::Component::ModularComponent`
2+
This base class is recommended for use by any component that is sufficiently complex to need modularization. It enables a component to be composed of multiple "sub-components" and coordinates the component lifecycle across all of them.
3+
4+
## Required Method Implementations
5+
6+
```ruby
7+
# The command for this component
8+
#
9+
# @return [void, String] components other than containers are not expected to return any value. Container
10+
# components are expected to return the command required to run the application.
11+
def command
12+
13+
# The modules that make up this component
14+
#
15+
# @param [Hash] context the context of the component
16+
# @return [Array<BaseComponent>] a collection of +BaseComponent+s that make up the modules of this component
17+
def modules(context)
18+
19+
# Whether or not this component supports this application
20+
#
21+
# @return [Boolean] whether or not this component supports this application
22+
def supports?
23+
```
24+
25+
## Exposed Instance Variables
26+
27+
| Name | Type
28+
| ---- | ----
29+
| `@modules` | [`Array<JavaBuildpack::Component::BaseComponent>`][]
30+
31+
32+
## Helper Methods
33+
34+
```ruby
35+
# Returns a copy of the context, but with a subset of the original configuration
36+
#
37+
# @param [Hash] context the original context of the component
38+
# @param [String] key the key to get a subset of the context from
39+
# @return [Hash] context a copy of the original context, but with a subset of the original configuration
40+
def sub_configuration_context(context, key)
41+
```
42+
43+
[`Array<JavaBuildpack::Component::BaseComponent>`]: extending-base_component.md

docs/extending.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ The buildpack provides a collection of base classes that may help you implement
5454
### [`JavaBuildpack::Component::BaseComponent`][]
5555
This base class is recommended for use by all components. It ensures that each component has a name, and that the contents of the context are exposed as instance variables (e.g. `context[:application]` is available as `@application`). In addition it provides two helper methods for downloading files as part of the component's operation.
5656

57+
### [`JavaBuildpack::Component::ModularComponent`][]
58+
This base class is recommended for use by any component that is sufficiently complex to need modularization. It enables a component to be composed of multiple "sub-components" and coordinates the component lifecycle across all of them.
59+
5760
### [`JavaBuildpack::Component::VersionedDependencyComponent`][]
5861
This base class is recommended for use by any component that uses the buildpack [repository support][] to download a dependency. It ensures that each component has a `@version` and `@uri` that were resolved from the repository specified in the component's configuration. It also implements the `detect` method with a standard implementation.
5962

@@ -63,13 +66,17 @@ The following example components are relatively simple and good for copying as t
6366
### Java Main Class Container
6467
The [Java Main Class Container](container-java_main.md) ([`lib/java_buildpack/container/java_main.rb`](../lib/java_buildpack/container/main.rb)) extends the [`JavaBuildpack::Component::BaseComponent`](../lib/java_buildpack/component/base_component.rb) base class described above.
6568

69+
### Tomcat Container
70+
The [Tomcat Container](container-tomcat.md) ([`lib/java_buildpack/container/tomcat.rb`](../lib/java_buildpack/container/tomcat.rb)) extends the [`JavaBuildpack::Component::ModularComponent`](../lib/java_buildpack/component/modular_component.rb) base class described above.
71+
6672
### Spring Boot CLI Container
6773
The [Spring Boot CLI Container](container-spring_boot_cli.md) ([`lib/java_buildpack/container/spring_boot_cli.rb`](../lib/java_buildpack/container/spring_boot_cli.rb)) extends the [`JavaBuildpack::Component::VersionedDependencyComponent`](../lib/java_buildpack/component/versioned_dependency_component.rb) base class described above.
6874

6975
[`config/components.yml`]: ../config/components.yml
7076
[`JavaBuildpack::Component::Application`]: extending-application.md
7177
[`JavaBuildpack::Component::BaseComponent`]: extending-base_component.md
7278
[`JavaBuildpack::Component::Droplet`]: extending-droplet.md
79+
[`JavaBuildpack::Component::ModularComponent`]: extending-modular_component.md
7380
[`JavaBuildpack::Component::VersionedDependencyComponent`]: extending-versioned_dependency_component.md
7481
[`lib/java_buildpack/container`]: ../lib/java_buildpack/container
7582
[`lib/java_buildpack/framework`]: ../lib/java_buildpack/framework

java-buildpack.iml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,8 +277,8 @@
277277
<orderEntry type="library" scope="PROVIDED" name="diff-lcs (v1.2.5, rbenv: 1.9.3-p545) [gem]" level="application" />
278278
<orderEntry type="library" scope="PROVIDED" name="docile (v1.1.3, rbenv: 1.9.3-p545) [gem]" level="application" />
279279
<orderEntry type="library" scope="PROVIDED" name="json (v1.8.1, rbenv: 1.9.3-p545) [gem]" level="application" />
280-
<orderEntry type="library" scope="PROVIDED" name="multi_json (v1.8.4, rbenv: 1.9.3-p545) [gem]" level="application" />
281-
<orderEntry type="library" scope="PROVIDED" name="parser (v2.1.5, rbenv: 1.9.3-p545) [gem]" level="application" />
280+
<orderEntry type="library" scope="PROVIDED" name="multi_json (v1.9.0, rbenv: 1.9.3-p545) [gem]" level="application" />
281+
<orderEntry type="library" scope="PROVIDED" name="parser (v2.1.7, rbenv: 1.9.3-p545) [gem]" level="application" />
282282
<orderEntry type="library" scope="PROVIDED" name="powerpack (v0.0.9, rbenv: 1.9.3-p545) [gem]" level="application" />
283283
<orderEntry type="library" scope="PROVIDED" name="rainbow (v2.0.0, rbenv: 1.9.3-p545) [gem]" level="application" />
284284
<orderEntry type="library" scope="PROVIDED" name="rake (v10.1.1, rbenv: 1.9.3-p545) [gem]" level="application" />
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
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'
19+
require 'java_buildpack/component/base_component'
20+
require 'java_buildpack/repository/configured_item'
21+
require 'java_buildpack/util/dash_case'
22+
require 'tmpdir'
23+
24+
module JavaBuildpack::Component
25+
26+
# A convenience base class for all components that are built modularly. In addition to the functionality inherited
27+
# from +BaseComponent+ this class also ensures that the collection of modules are iterated over for each lifecycle
28+
# event.
29+
class ModularComponent < BaseComponent
30+
31+
# Creates an instance. In addition to the functionality inherited from +BaseComponent+, a +@sub_components+
32+
# instance variable is exposed.
33+
#
34+
# @param [Hash] context a collection of utilities used by components
35+
# @param [Block, nil] version_validator an optional version validation block
36+
def initialize(context, &version_validator)
37+
super(context)
38+
@sub_components = supports? ? sub_components(context) : []
39+
end
40+
41+
# @macro base_component_detect
42+
def detect
43+
supports? ? @sub_components.map { |m| m.detect }.flatten.compact : nil
44+
end
45+
46+
# @macro base_component_compile
47+
def compile
48+
@sub_components.each { |m| m.compile }
49+
end
50+
51+
# @macro base_component_release
52+
def release
53+
@sub_components.map { |m| m.release }
54+
command
55+
end
56+
57+
protected
58+
59+
# @!macro [new] modular_component_command
60+
# The command for this component
61+
#
62+
# @return [void, String] components other than containers are not expected to return any value. Container
63+
# components are expected to return the command required to run the application.
64+
def command
65+
fail "Method 'command' must be defined"
66+
end
67+
68+
# @!macro [new] modular_component_sub_components
69+
# The sub_components that make up this component
70+
#
71+
# @param [Hash] context the context of the component
72+
# @return [Array<BaseComponent>] a collection of +BaseComponent+s that make up the sub_components of this
73+
# component
74+
def sub_components(context)
75+
fail "Method 'sub_components' must be defined"
76+
end
77+
78+
# Returns a copy of the context, but with a subset of the original configuration
79+
#
80+
# @param [Hash] context the original context of the component
81+
# @param [String] key the key to get a subset of the context from
82+
# @return [Hash] context a copy of the original context, but with a subset of the original configuration
83+
def sub_configuration_context(context, key)
84+
c = context.clone
85+
c[:configuration] = context[:configuration][key]
86+
c
87+
end
88+
89+
# @!macro [new] modular_component_supports
90+
# Whether or not this component supports this application
91+
#
92+
# @return [Boolean] whether or not this component supports this application
93+
def supports?
94+
fail "Method 'supports?' must be defined"
95+
end
96+
97+
end
98+
99+
end

lib/java_buildpack/component/versioned_dependency_component.rb

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,7 @@ def initialize(context, &version_validator)
4444
end
4545
end
4646

47-
# If the component should be used when staging an application
48-
#
49-
# @return [Array<String>, String, nil] If the component should be used when staging the application, a +String+ or
50-
# an +Array<String>+ that uniquely identifies the component (e.g.
51-
# +openjdk=1.7.0_40+). Otherwise, +nil+.
47+
# @macro base_component_detect
5248
def detect
5349
@version ? id(@version) : nil
5450
end

0 commit comments

Comments
 (0)