In this second part we will take a detailed tour on how to use the code I share with you for environment detection and automatic configuration of your web app with Spring 3.1.
The Code
I share both zips with you to use it as you like. I only ask you to respect the authorship.
Profile-detector jars and pom. (Maven projects that enables the environment detection feature)
Example web-app with different configurations (Example web app project with automatic configuration based on the environment)
To make our application environment aware we need to follow the following steps:
1.- Use Spring 3.1
2.- Add the profile-detector dependency to our pom
3.- Modify the web.xml file so we can initialize Spring prior anything else happens
4.- Add integration classes so we can declare environments and sensors
5.- Extend integration class to define you own environment parameters
6.- Select which sensors we are going to use
7.- Define known environment profiles with its sensor values
8.- Create different configurations for our needs
9.- Map each configuration with corresponding environment
10.- Optionally you can add beans for different configurations
Dissecting the example web app
Let's see what's inside the example web app while we follow the steps so you can use the code in it for your own projects.
I will assume you know how to use maven, how to add Spring 3.1.0.RELEASE as dependency, and how to install the profile-detector project on your repository. (Otherwise you should chek: Spring and maven, Install a jar to your repository). So let's skip step 1.
2. Add profile-detector as dependency
Add to your pom:
(Make sure you installed the profile-detector on your maven repository)
3. Add a Spring initializer to the web.xml
To the existing web.xml with Spring defined:
Add an additional context parameter:
This way we tell Spring that it should look for this class, instantiate and use it for its own initialization,. We will use this hook to add the environment detection step.
4. Add integration classes
The classes I added over profile-detector project and integrating it with spring are:
- AmbientBasedContextInitializerSupport
- AmbientConfiguration
- SpringBasedConfigurationSupport
These classes enable the feature of detecting the environment in the initilization phase of Spring.
You should take a look at the core of AmbientBasedContextInitializerSupport. This class does the magic of putting it all together:
As you can see, it makes a call to detect the current "AmbientProfile" which would represent the current environment using the profile-detector code. Then it asks its subclass for an "AmbientConfiguration" which represents the knowledge to adapt the current configuration to match the corresponding AmbientProfile.
5. Extend AmbientBasedContextInitializerSupport
If you payed attention to the web.xml snippet we declared a "com.tenpines.example.ambients.ExampleSpringContextInitializer" class. This class extends the "AmbientBasedContextInitializerSupport" class and enables the application to define its own characteristics.
This class will be instantiated by Spring to auto initialize itself.
6. Select which sensors to use
For the sake of the example I used only one sensor, the "HostnameSensor". This sensor takes the current machine's hostname and is probably the simplest way to detect different environments.
Implementing the "getUsedSensors" you tell which sensors to use:
Every sensor you declare in this method will be used any time the application starts to detect which environmet is current.
There are more predefined sensors you can use, and you can define yours just implementing the interface AmbientSensor. All the sensor have to take a snapshot of some environment variable and express it as a String so it can be compared later:
- AvailableFileRootsSensor
It gives you all the file roots available as a single String - AvailableProcessorsSensor
It tells you the number of available processors on the current machine - CurrentSytemUserSensor
Tells the name of the current user as reported by the operating system - CurrentWorkingDirSensor
The name of the current working dir - HostIpSensor
The current ip address - MaxMemorySensor
The max memory available to the running virtual machine - OperatingSystemSensor
A description of the current operating system - SystemArchitectureSensor
A description of the current machine architecture - VmDescriptionSensor
A decription of the running java virtual machine
7. Define your known environments
After selecting the sensors you should teach the application which sensors values should expect for each known environment.
You define different known environemnts (AmbientProfiles) to discriminate where is your code running. This is intentionally separated from the possible configurations (AmbientConfiguration) as a configuration could be shared by different environments (probably in development).
The "HOME_PROFILE" is my home machine profile. You should change the value to your own hostname in the "ALIEN_PROFILE" otherwise you will get and error indicating that the current environment is not known to the application when running the example.
[The last part of the init method declares a map, so we know which configuration goes with each profile]
8. Create different configurations
In this example there are two classes:
- ExampleHomeAmbientConfiguration
This will be the configuration for my machine - ExampleAlienAmbientConfiguration
This should be the configuration for your machine
They represent different configurations and also they use different spring profiles for the beans. When one configuration is elected according to the AmbientProfile, Spring is initialized with a specific profile:
Each configuration defines the Spring profile to use when activated:
Build your own configurations according to your needs. I my own project I change the logging options so in development mode I see everything on the STDOUT, but in production it goes to a rolling file.
9. Map each profile with its configuration
This is done in the method "getConfigurationFor" overrided from the "AmbientBasedContextInitializerSupport" class. You should use any criteria. I used a map.
The init method initialized the map for each profile.
10. Use different set of beans for each configuration
Finally and depending on your needs you can define different sets of bean to use for each configuration.
I mapped a bean profile for each configuration. The beans are declared in the main spring configuration file web-application-context.xml.
The syntax is pretty self-explanatory. You can see more on the Spring 3.1 tutorials.
Thanks for watching!
No comments:
Post a Comment