What you will learn:
Specific subjects you will gain experience with:
Estimated time to complete: 30 minutes
Quick instructions for this exercise have been embedded within
the lab materials in the form of TODO comments. To display them,
open the Tasks
view (Window >> Show View >>
Tasks (not Task
List)). Use the view’s small down arrow to select
a Configure Contents…
menu, you’ll find the instructions are easy to follow if you
configure TODOs to display On any element in
the same project
.
Occasionally, TODO’S defined within XML files disappear
from the Tasks
view (i.e. gaps in the
number sequence). To correct this, go to Preferences >> General >> Editors
>> Structured Text Editor >> Task Tags
pane. Check Enable searching for Task
Tags
and click Clean and Redetect
Tasks
. On the Filters
tab,
ensure XML content type is checked.
Spring provides several features that help you reduce the amount of application configuration code. In this section you’ll gain experience with one of them called bean definition inheritance.
(TODO 01) Inside the rewards
package, open the test class called RewardNetworkTests
. As you can see Spring is
being configured by using TestInfrastructureConfig
in the same
package.
Open TestInfrastructureConfig.java
and you will see an empty @ImportResources
annotation. We will use
this to load our two XML configuration files: test-infrastructure-config.xml
and application-config.xml
. Modify it now.
Note | |
---|---|
You can use Keep in mind that you should include the file paths starting
from inside the classpath root folders ( |
Bean definition inheritance is useful when you have several
beans that should be configured the same way. It lets you define
the shared configuration once, then have each bean inherits from
it. In the rewards
application, there
is a case where bean definition inheritance makes sense. Recall
there are three JDBC-based repositories, and each repository needs
the same dataSource
.
(TODO 02) Inside src/main/java
within the rewards.internal
package,
open application-config.xml
. Note how
the property
tag instructing Spring to
set the dataSource
is currently
duplicated for each repository.
Now in application-config.xml
,
create an abstract bean named abstractJdbcRepository
that centralizes the
dataSource
configuration. You will not
need to define the class for this bean, but you should define the
dataSource
property and set it with a
reference to the dataSource
bean.
Next, update each repository bean so it extends from your abstractJdbcRepository
bean definition. The
repository beans will no longer need to set their own dataSource
properties since this is now
defined by the abstract bean definition.
Re-run RewardNetworkTests
. It
should still pass.
(TODO 03) In this section, you’ll gain experience with
using the <context:property-placeholder>
,
element. Specifically, you will move the configuration of your
embedded-database
from test-infrastructure-config.xml
into a .properties
file, then declare a <context:property-placeholder>
element
to apply the configuration. By doing this, you’ll make it
easier for administrators to safely change your configuration.
Create a file named application.properties
in the root of the
classpath. Add the following properties:
schemaLocation=classpath:rewards/testdb/schema.sql testDataLocation=classpath:rewards/testdb/data.sql
Notice how these values match the current script values of the
embedded dataSource
in test-infrastructure-config.xml
.
Within test-infrastructure-config.xml
, replace each
property value configured for your embedded-database
with a placeholder. The
placeholder name should match the respective property name in your
properties file. The placeholders follow the syntax ${placeholder}
If you run the RewardNetworkTests
at this point it will fail. One more step left to
complete…
In test-infrastructure-config.xml
,
declare an instance of the <context:property-placeholder>
element. Set its location
attribute to
point to your properties file. Remember that this configuration
will be automatically detected by Spring and called before any
other bean is created. No other configuration is necessary.
Now re-run your RewardNetworkTests
,
it should pass.
Tip | |
---|---|
Even if you get green on your first attempt, try experimenting with some failure scenarios. For example, try misspelling a placeholder, property name, or property value and see what happens. |
(TODO 04) Using the <import/>
tag is often a good idea when working with multiple configuration
files. Return to RewardNetworkTests
.
Note how all the configuration files required to run the system
test are listed in this file. Now suppose you added another
configuration file. You would have to update your test code to
accommodate this change.
The import tag allows you to create a single 'master' configuration file for each environment that imports everything else. This technique can simplify the code needed to bootstrap your application and better insulate you from changes in your application configuration structure.
Open test-infrastructure-config.xml
and add an <import/>
tag to
import application-config.xml
. Within
RewardNetworkTests
, remove the
reference to application-config.xml
from the array of configuration files. Rerun the test, it should
pass.