|
@@ -1,5 +1,5 @@
|
1
|
1
|
# Bean Flavored Learner Lab
|
2
|
|
-* **Objective** - to implement a `ZipCodeWilmington` class which _mediates_ a _composite_ `Students` and `Instructors` _singleton_ reference.
|
|
2
|
+* **Objective** - to register a `Classroom` bean which _mediates_ a _composite_ `Students` and `Instructors` bean reference.
|
3
|
3
|
* **Purpose** - to demonstrate the use of
|
4
|
4
|
* Bean registration
|
5
|
5
|
* Dependency Injection
|
|
@@ -18,7 +18,7 @@
|
18
|
18
|
## Developmental Notes
|
19
|
19
|
* Do NOT clone this repository until completing `Part 0.0`
|
20
|
20
|
* You may structure this project and the packaging how you please, however keep in mind that `@Configuration` scans from current directory down.
|
21
|
|
-* This project is nearly identical to the `LearnerLab` completed in the past until `Part 9`
|
|
21
|
+* Until `Part 9`, this project is nearly identical to the `LearnerLab` completed in the past.
|
22
|
22
|
|
23
|
23
|
### Part 0.0 - Generating Project
|
24
|
24
|
* Navigate to [start.spring.io](https://start.spring.io/)
|
|
@@ -29,14 +29,15 @@
|
29
|
29
|
* After the project has completed downloading, navigate to the download directory and unzip the project folder.
|
30
|
30
|
* After unzipping the project folder, open the project via its `pom.xml` from IntelliJ > File > Open
|
31
|
31
|
* Be sure to `Open as Project` when prompted
|
32
|
|
-* At the root directory of the project, clone this repository and continue forth.
|
|
32
|
+* At the root directory of the project, clone this repository.
|
|
33
|
+* Move all files from the `demo` project generated by `start.spring.io`, into the newly cloned `learnerlab` folder.
|
33
|
34
|
|
34
|
35
|
|
35
|
36
|
### Part 1.0 - Create `Person` Class
|
36
|
37
|
* Create a `Person` class.
|
37
|
38
|
* The class should declare a `final` field named `id` of type `long`.
|
38
|
39
|
* The class should declare a field named `name` of type `String`.
|
39
|
|
- * `Person` constructor should have a parameter of type `long` which sets the `id` field to the respective value.
|
|
40
|
+ * `Person` constructor should have a parameter of type `Long id, String name` which sets each of the fields to their respective value.
|
40
|
41
|
* The class should define a `getId()` method which returns the `Person` object's `id` field.
|
41
|
42
|
* The class should define a `getName()` method which returns the `Person` object's `name` field.
|
42
|
43
|
* The class should define a `setName()` method which sets the `Person` object's `name` field.
|
|
@@ -72,7 +73,7 @@
|
72
|
73
|
* `Teacher` should declare a `lecture` method signature:
|
73
|
74
|
* Method name: `lecture`
|
74
|
75
|
* Method parameters:
|
75
|
|
- * `Learner[] learners`
|
|
76
|
+ * `Iterable<? extends Learner> learners`
|
76
|
77
|
* `double numberOfHours`
|
77
|
78
|
* Method return-type: `void`
|
78
|
79
|
|
|
@@ -87,35 +88,68 @@
|
87
|
88
|
* `numberOfHours` should be evenly split amongst the learners.
|
88
|
89
|
* `double numberOfHoursPerLearner = numberOfHours / learners.length;`
|
89
|
90
|
|
|
91
|
+### Part 6.0 - Create `People`
|
|
92
|
+* Create an abstract `People` class
|
|
93
|
+ * The class signature should be parameterized with `PersonType` such that `PersonType` is a sub class of `Person`.
|
|
94
|
+ * The class should implement `Iterable` of type `PersonType`.
|
|
95
|
+ * Upon construction `People` should consume a `List` of `PersonType` and set it to a respective `personList` field.
|
|
96
|
+ * The class should define a constructor which consumes a variable number of `PersonType` objects and sets the `personList` field respectively.
|
|
97
|
+ * The class should define a method named `add` which adds a `PersonType` to the `personList`.
|
|
98
|
+ * The class should define a method named `remove` which removes a `PersonType` from the `personList`.
|
|
99
|
+ * The class should define a method named `size` which returns the size of `personList`.
|
|
100
|
+ * The class should define a method named `clear` which clears our `personList` field.
|
|
101
|
+ * The class should define a method named `addAll` which adds an `Iterable` of `PersonType` objects to the composite `personList`.
|
|
102
|
+ * This method will **NOT** take an argument of `Collection<PersonType>`
|
|
103
|
+ * The class should define a method named `findById` which makes use of a `long id` parameter to return a `PersonType` object with the respective `id` field.
|
|
104
|
+ * The class should define a method named `findAll` which returns the composite `personList`.
|
|
105
|
+
|
|
106
|
+
|
90
|
107
|
-
|
91
|
|
-### Part 6.0 - Create `Students`
|
|
108
|
+### Part 7.0 - Create `Students`
|
92
|
109
|
* Create a `Students` class.
|
93
|
|
- * The class should be an _unextendable_ subclass of the `People` class.
|
|
110
|
+ * The class should be a subclass of `People` of parameterized type `Student`.
|
94
|
111
|
* The class should consume a variable number of `Student` objects upon construction and pass them to the super constructor.
|
95
|
112
|
|
96
|
113
|
-
|
97
|
|
-### Part 7.0 - Create `Instructors`
|
|
114
|
+### Part 8.0 - Create `Instructors`
|
98
|
115
|
* Create a `Instructors` class.
|
99
|
|
- * The class should be an _unextendable_ subclass of the `People` class.
|
|
116
|
+ * The class should be a subclass of `People` of parameterized type `Instructor`.
|
100
|
117
|
* The class should consume a variable number of `Instructor` objects upon construction and pass them to the super constructor.
|
101
|
118
|
|
102
|
119
|
|
103
|
120
|
|
104
|
121
|
-
|
105
|
|
-### Part 8.0 - Create `Classroom`
|
|
122
|
+### Part 9.0 - Create `Classroom`
|
106
|
123
|
* Create a `Classroom` class.
|
107
|
124
|
* The class should consume and set composite reference to an `Instructors` and `Students` object upon construction
|
108
|
125
|
* The class should define a method `hostLecture` which makes use of a `Teacher teacher, double numberOfHours` parameter to host a `lecture` to the composite `personList` field in the `students` reference.
|
109
|
126
|
|
110
|
127
|
|
111
|
128
|
-
|
112
|
|
-## Part 9.0 - Creating `Configuration` classes
|
|
129
|
+## Part 10.0 - Creating `Configuration` classes
|
113
|
130
|
* Each of the following `Config` classes should have a class-signature annotation of `@Configuration`
|
114
|
131
|
* this annotation tells spring to scan for `@Bean` definitions within the scope of the class, and register them to the [IOC Container](https://www.tutorialspoint.com/spring/spring_ioc_containers.htm) for `Inject` and `Autowire` use later.
|
|
132
|
+* Classroom should define getters for each of its fields.
|
115
|
133
|
* **Tip:** if testing fails, begin researching and attempting to use the `@Qualifier` annotation.
|
116
|
134
|
|
|
135
|
+### Developmental Notes
|
|
136
|
+* `@Autowired`
|
|
137
|
+ * injects bean by type
|
|
138
|
+ * can be used alone.
|
|
139
|
+ * If is used alone, it will be wired by type
|
|
140
|
+ * If more than one bean of same type are declared in the container `@Autowired` does not know which beans to use for injection.
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+* `@Qualifier`
|
|
144
|
+ * injects bean by specified name
|
|
145
|
+ * supports fields, setter, constructors and multi-argument methods injection
|
|
146
|
+ * together with `@Autowired`, clarifies which beans to be wired by specifying the bean name (wired by name)
|
|
147
|
+
|
|
148
|
+<img src = "https://www.logicbig.com/tutorials/spring-framework/spring-core/javaconfig-methods-inter-dependency/images/bean-params.png">
|
|
149
|
+
|
|
150
|
+
|
117
|
151
|
-
|
118
|
|
-### Part 9.1 - Create `StudentConfig`
|
|
152
|
+### Part 10.1 - Create `StudentConfig`
|
119
|
153
|
* **Note:** The creation of this class will demonstrate an implementation of bean registration in Spring.
|
120
|
154
|
* The class should define a method named `currentStudents()` which returns a `Students` representative of the current cohort of students.
|
121
|
155
|
* the method should be annotated with `@Bean(name = "students")`
|
|
@@ -124,49 +158,53 @@
|
124
|
158
|
* The class should define a bean named `previousStudents()` which returns a `Students` representative of the previous cohort of students.
|
125
|
159
|
|
126
|
160
|
-
|
127
|
|
-### Part 9.2 - Create `InstructorsConfig`
|
|
161
|
+### Part 10.2 - Create `InstructorsConfig`
|
128
|
162
|
* The class should define a bean named `tcUsaInstructors()` which returns an `Instructors` representative of the Tech Connect USA instructors.
|
129
|
163
|
* The class should define a bean named `tcUkInstructors()` which returns an `Instructors` representative of the Tech Connect UK instructors.
|
130
|
|
-* The class should define a bean named `allInstructors` which returns all `Instructors` employed at ZipCodeWilmington
|
|
164
|
+* The class should define a bean named `instructors` which returns all `Instructors` employed at ZipCodeWilmington
|
|
165
|
+ * annotate this bean with `@Primary`
|
|
166
|
+ * this ensures Spring will inject this bean in the case that an `Autowire` annotation is not supplied with a `Qualifier` annotation
|
131
|
167
|
|
132
|
168
|
|
133
|
169
|
|
134
|
170
|
-
|
135
|
|
-### Part 9.3 - Create `ClassroomConfig`
|
136
|
|
-* The class should define a bean named `currentCohort()` which returns an `Classroom` object whose dependencies are `allInstructors` and `students`
|
137
|
|
-* The class should define a bean named `previousCohort()` which returns an `Classroom` object whose dependencies are `allInstructors` and `previousStudents`
|
|
171
|
+### Part 10.3 - Create `ClassroomConfig`
|
|
172
|
+* The class should define a bean named `currentCohort()` which returns a `Classroom` object whose dependencies are `instructors` and `students`
|
|
173
|
+* The class should define a bean named `previousCohort()` which returns an `Classroom` object whose dependencies are `instructors` and `previousStudents`
|
138
|
174
|
* **Note:** [it is sometimes useful](https://www.boraji.com/spring-dependson-annotation-example) (although not always necessary) to use the `@DependsOn` annotation to help the compiler and other readers of the code to understand what order beans should be executed.
|
139
|
|
- * `@DependsOn({"allInstructors", "students"})`
|
|
175
|
+ * `@DependsOn({"instructors", "students"})`
|
140
|
176
|
|
141
|
177
|
|
142
|
178
|
|
143
|
179
|
|
144
|
180
|
-
|
145
|
|
-## Part 10.0 - Test `Config` classes
|
|
181
|
+## Part 11.0 - Test `Config` classes
|
146
|
182
|
* Each of the following `Test` classes should be annotated with
|
|
183
|
+ * `@RunWith(SpringRunner.class)`
|
|
184
|
+ * enforces which strategy `junit` should use to run tests
|
147
|
185
|
* `@SpringBootTest`
|
148
|
186
|
* indicates that this class is a Spring Boot test class
|
149
|
187
|
* provides support to scan for a `ContextConfiguration` that tells the test class how to load the `ApplicationContext`.
|
150
|
188
|
* If no `ContextConfiguration` classes are specified as a parameter to the `@SpringBootTest` annotation, the default behavior is to load the `ApplicationContext` by scanning for a `@SpringBootConfiguration` annotation on a class in the package root.
|
151
|
|
-* Each bean can be injected into the class scope using `@Autowired` along with `@Resource(name = "beanname")`
|
|
189
|
+* Each bean can be injected into the class scope using `@Autowired` along with `@Qualifier(name = "beanname")`
|
152
|
190
|
|
153
|
191
|
|
154
|
192
|
|
155
|
193
|
-
|
156
|
|
-### Part 10.1 - Test `StudentConfig` Class
|
|
194
|
+### Part 11.1 - Test `StudentConfig` Class
|
157
|
195
|
* Create a `TestStudentConfig` class in the `test` package.
|
158
|
196
|
* The class should ensure that each `Bean` in the `StudentConfig` class is configured as expected.
|
159
|
197
|
* **Tip:** You can use the `toString` method to get a representation of the aggregate state of any `People` object.
|
160
|
198
|
|
161
|
199
|
|
162
|
200
|
-
|
163
|
|
-### Part 10.2 - Test `InstructorConfig` Class
|
|
201
|
+### Part 11.2 - Test `InstructorConfig` Class
|
164
|
202
|
* Create a `TestInstructorConfig` class in the `test` package.
|
165
|
203
|
* The class should ensure that each `Bean` in the `TestInstructorConfig` class is configured as expected.
|
166
|
204
|
|
167
|
205
|
|
168
|
206
|
-
|
169
|
|
-### Part 10.3 - Test `ClassroomConfig` Class
|
|
207
|
+### Part 11.3 - Test `ClassroomConfig` Class
|
170
|
208
|
* Create a `TestClassroomConfig` class in the `test` package.
|
171
|
209
|
* The class should ensure that each `Bean` in the `TestClassroomConfig` class is configured as expected.
|
172
|
210
|
|
|
@@ -177,14 +215,17 @@
|
177
|
215
|
|
178
|
216
|
|
179
|
217
|
## Part 11.0 - Using `@Component`
|
180
|
|
-* Annotating a class signature class with `@Component` allows Spring to register this class as a `Bean` implicitly.
|
|
218
|
+* Annotating a class signature with `@Component` allows Spring to register the class as a `Bean` implicitly.
|
|
219
|
+
|
|
220
|
+
|
181
|
221
|
-
|
182
|
222
|
### Part 11.1 - Create `Alumni` Class
|
183
|
223
|
* Create an `Alumni` component which autowires `Students` of the previous cohort and `Instructors`
|
184
|
224
|
* Create an `executeBootcamp` method which teaches each `Student` in the composite `Students` a `totalNumberOfHours` of `1200`.
|
185
|
225
|
* Annotate this method with `@PostConstruct`
|
186
|
226
|
* denotes that this method must be executed before the class is put into an IoC container
|
|
227
|
+* Create a getter for each of the fields.
|
187
|
228
|
|
188
|
229
|
-
|
189
|
230
|
### Part 11.2 - Test `Alumni` Class
|
190
|
|
-* Write a test class which ensures that each `Student` in the `Alumni` class has been taught `1200` hours upon injection of the `Alumni` dependency.
|
|
231
|
+* Write a test class which ensures that each `Studyent` in the `Alumni` class has been taught `1200` hours upon injection of the `Alumni` dependency.
|