Introduction to Spring (part2)
In this LDS Java Stack training we will build on what we learned in the Introduction to Spring training. We will be discussing some development productivity concepts such as xml configuration extensions (namespace handlers) and annotations.
Prerequisites
- Must have previously completed the Introduction to the Java Stack training.
- Must have previously completed the Introduction to Spring training (and if your dog somehow ate the electronic copy of your labs - Media:IntroductionToSpringCheat.zip).
- Basic knowledge of Java language.
- Basic knowledge of XML syntax and structure.
- A workstation running Windows, Linux, or Mac OS.
- A desire to learn.
Outline
Overview
Xml Configuration Extension (Namespace Handlers)
- Spring bean lifecycle
- What they provide
- How they work
- Handlers that Spring provides
JSR 250 (Common) Annotations
- Bean Lifecycle
- @PostConstruct
- Annotations / Bean Post Processors
Spring Annotations
- Component scanning
- Stereotype annotations
- @Scope
JSR 330 (DI) Annotations
- @Named / @Inject
Slide Deck
Media:IntroductionToSpring(part2).pptx
Xml Schema-based Configuration Presentation
Lab 1 XML Schema-based Configuration
Create a reusable List of Rabbits using the Spring util xml schema-based configuration
Documentation can be found here: http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/xsd-config.html#xsd-config-body-schemas-util
- Add a util namespace to your bean definition file
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd"> <!-- definitions here --> </beans>
- Define the list with the appropriate namespace prefix
<util:list id="rabbitList"> </util:list>
- Copy the values from the anonymous list in the rabbits property of the Farm definition to your util:list
<util:list id="rabbitList"> <bean class="org.lds.training.Rabbit"> <constructor-arg name="weight" value="10.5" /> </bean> <bean class="org.lds.training.Rabbit"> <constructor-arg name="weight" value="2.25" /> </bean> <bean class="org.lds.training.Rabbit"> <constructor-arg name="weight" value="5.0" /> </bean> </util:list>
- Inject the util:list into the Farm by id
<property name="rabbits" ref="rabbitList" />Lab 1 Solution

Bean Initialization Presentation

Lab 2 Bean Initialization
Create an init method using @PostConstruct
- In the LDSTech IDE add the following inside of the properties element of your pom.xml (Maven defaults to Java 5 and these annotations are not directly include in Java until Java 6)
<maven.compiler.source>1.6</maven.compiler.source> <maven.compiler.target>1.6</maven.compiler.target>
Then right click on your project and select Maven -> Update Project Configurations
- Create an init method (that prints something out) on your Farm object
- Annotate the method with @PostConstruct
- Run your tester to see if the init method was called (it shouldn’t have been)
- Modify your bean definition file to contain the following:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <context:annotation-config /> </beans>
Lab 2 Soution

Spring Component Annotations Presentation

Lab 3 Spring Component Annotations
Change SomeBean to be configured by annotations only
- Make sure you are loading your SomeBean with the following: SomeBean someBean = context.getBean(SomeBean.class);, or if you are loading it by id please change the id to match the default id of someBean
- Comment out or remove the SomeBean configuration <bean id="someBean" ... /> in the bean definition file
- Annotate SomeBean with @Component
- Also annotate it with @Scope("prototype") just for the fun of it
- Add the component-scan element to the bean definition file
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <context:component-scan base-package="org.lds.training" /> </beans> * Run your tester to make sure that SomeBean is still registered and prints its message
Lab 3 Solution

DI Annotations (JSR 330) Presentation

Lab 4 DI Annotations (JSR 330)
Convert your farm to be configured via annotations instead of xml
- Add the jsr-330 dependency to your pom.xml
<dependency> <groupId>javax.inject</groupId> <artifactId>javax.inject</artifactId> <version>1</version> </dependency>
- Add the component scanner to the bean definition file
- The component scanner contains the annotation-config configurations as well, so that can be removed
- Remove the farm definition from the xml bean definition file
- Annotate the farm object with @Component
How do you handle the initialization of the list of rabbits?
- Annotate the rabbit list with @Resource(name="rabbitList") (you might expect @Inject @Named("rabbitList") to inject the list appropriately but it does not). We felt that @Resource was enough of an edge case that we did not cover it, but it is a JSR 250 annotation that will find and inject a resource of a given name/id.
If you have not already done so, in your application context (bean definition) xml file, set the name of the rabbit with scope protoype to be prototypeRabbit and the name of the rabbit with scope singleton to be singletonRabbit or something similar to distinguish them.
<property name="name" value="Singleton Rabbit" /> <property name="name" value="Prototype Rabbit" />
- Add a Rabbit prizeRabbit attribute if you don’t already have one, and inject your prototypeRabbit
public class Farm { @Inject @Named("prototypeRabbit") private Rabbit prizeRabbit; ... }
Can you remove the prototypeRabbit and singletonRabbit declarations from the definition file and handle them in annotations?
- Add a Chicken class as follows:
import org.springframework.stereotype.Component; @Component public class Chicken { private String name = "Chicken Licken"; public String getName() { return name; } public void setName(String name) { this.name = name; } }
- Add a farm animals method as follows
public void printFarmAnimals(Chicken chicken, Rabbit singletonRabbit) { System.out.println("Printing the inject farm animals *****************"); System.out.println(prizeRabbit.getName()); System.out.println(chicken.getName()); System.out.println(singletonRabbit.getName()); for (Rabbit rabbit : rabbits) { System.out.println(rabbit.getName()); } }
- Annotate this method with @Inject, and annotate the singletonRabbit parameter with @Named("singletonRabbit") specifying the id of your singleton rabbit
- Then run your SpringTester class
Lab 4 Solution


