In the first article we will look at how to write your first Java Spring based class. The theme of our application we are going to write in this series will be a "Popular Talent Show", so our talent show will cater to a variety of talents, and we need to cater to the performers, so we will first write an interface:
- public interface Performer {
- void Perform() throws PerformaceException;
- }
And to ensure that something goes wrong during a performance we have:
- public class PerformaceException extends Exception {
-
-
-
- private static final long serialVersionUID = 3648369653354254918L;
- }
Where you can give any message or information, for the time being it is empty with just a UID. So without fail we introduce the first performer who can handle at a given instance n number of spinning balls:
- public class Juggler implements Performer {
- private int _ballCount = 5;
- public Juggler(){
- }
- public Juggler(int ballCount){
- _ballCount = ballCount;
- }
- @Override
- public void Perform() throws PerformaceException {
-
- System.out.println("JUGGLING " + _ballCount + " BALLS");
- }
- }
As you can see we have an overloaded constructor through which I can inject the count of balls the performer can handle at a given point of time.
Ok, now everything seems to be ready, all we need to do is notify our Spring framework about the new performer: what we need is the XML file through which we are going to do that:
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
- <bean id="mike" class="spring.decoded.big.awards.Juggler">
- <constructor-arg value="10" />
- </bean>
- </beans>
The above file is a Spring bean definition file where we define our beans or in plain simple words, we have defined that class Juggler should be identified with the name "Mike" so that whenever he is called upon to ask to perform, we can use this name to call him out.
Another interesting thing to note is that we can explicitly pass various counts of balls to Mike without touching the class definition, how Spring allows us to do that is by the use of: "constructor-arg" which is specified for a given bean (or class in vanilla terms).
So, it's time that we introduce to you the first performer for the day, "Mike":
- public static void main(String[] args) throws PerformaceException {
-
- System.out.println("Starting the show....");
- ApplicationContext context = new ClassPathXmlApplicationContext("spring/decoded/big/awards/big-awards.xml");
- Performer performer = (Performer) context.getBean("mike");
- if (performer == null)
- System.out.println("Mike is missing from the show...");
- performer.Perform();
- }
Right-click on your class which has the main method and select "Run As" -> "Java Application", if everything goes fine, you should see the following in the console terminal:
So that's it for the first chapter, you saw how to set a small class using a Spring container and get its instances. So of all these things what was so great about Spring? Why do so many things to invoke such a trivial method. Well the first thing to make a note of is that no where you used a keyword "new" to instantiate your performer, that was done for you by the Spring framework, which handles the object state* on its own; instead you worry about when and where to allocate (using new) an instance and when not to.
Note: By object state we mean, whether it needs to be a singleton object shared by all callers, or one should get a new instance every time the class or bean definition is queried for from the Spring framework.
Constructor Injection
We will cover more details about constructor injection in Spring; until now we saw:
- How you are spared from creating objects for your classes and delegate that work to Spring
- How to inject primitive values to the classes using constructor injection
In this chapter we will see how to pass reference arguments to the classes rather than passing primitive types. In our "Popular Talent Show" we saw a juggler so far. Next we have another performer who can juggle balls as well as sing, both at the same time, which is a very unique talent, so to showcase that let us write an interface first:
- public interface Song
- {
- void Sing();
- }
Next we will have a concrete implementation of this type:
- public class Singer implements Song
- {
- private static String[] Lines = {
- "I'm never lettin' go",
- "No, no, no, won't let go",
- "When you want it, when you need it",
- "You'll always have the best of me",
- "I can't help it, believe it",
- "You'll always get the best of me",
- "I may not always know what's right",
- "But I know I want you here tonight",
- "Gonna make this moment last for all your life",
- "Oh ya this is love and it really means so much",
- "I can tell from every touch"
- };
- @Override
- public void Sing()
- {
- for(int i = 0 ; i < Lines.length ; i++)
- {
- System.out.println(Lines[i]);
- }
- }
- }
That's cool. So far, we have a favorite song who our singer would be singing, this popular song of Bryan Adams (his favorite singer) on the show along with Juggling, so let's create a class for the SingingJuggler:
- public class SingingJuggler extends Juggler
- {
- private Song _song;
- public SingingJuggler(Song song)
- {
- super();
- _song = song;
- }
- public SingingJuggler(int beanCount, Song song){
- super(beanCount);
- _song = song;
- }
- public void Perform() throws PerformaceException
- {
- super.Perform();
- System.out.println("While singing...");
- _song.Sing();
- }
- }
Great. So we have everything ready, now we need to declare them in the Spring 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"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
- <bean id="mike" class="spring.decoded.big.awards.Juggler">
- <constructor-arg value="10" />
- </bean>
- <bean id="bestOfMe" class="spring.decoded.big.awards.Singer" />
- <bean id="john" class="spring.decoded.big.awards.SingingJuggler">
- <constructor-arg value="11" />
- <constructor-arg ref="bestOfMe"/>
- </bean>
- </beans>
As we did previously, we declared the Singer class as a bean with id "bestOfMe" to identify it and interestingly our Singing Juggler needs this bean, so we are injecting the same again through a constructor-arg but as a reference, using the "ref" attribute.
So, without further delay, let's invite our new performer to showcase his talent:
- public static void main(String[] args) throws PerformaceException
- {
-
- System.out.println("Starting the show....");
- Stage stage = Stage.getIstance();
- stage.SetUp();
- ApplicationContext context = new ClassPathXmlApplicationContext("spring/decoded/big/awards/big-awards.xml");
- Performer performer = (Performer)context.getBean("mike");
- if(performer == null)
- System.out.println("Mike is missing from the show...");
- performer.Perform();
- System.out.println("Moving onto next performance : ");
- performer = (Performer)context.getBean("john");
- if(performer == null)
- System.out.println("John is missing from the show...");
- performer.Perform();
- }
Let's run the application to see the output in the console:
Great, so easy and simple, cheers and enjoy until the next chapter.
How to perform Setter Injections using the Spring framework
we will cover how to perform setter injections using the Spring framework. This is another way of resolving dependencies in your class; let's see it using a use case of how one can leverage this.
In our Popular Talent Show we have a new performer, Shaun, who can play any sort of instrument, so to represent that, let's write a generic instrument interface:
- public interface Instrument
- {
- void Play();
- }
Next we need a class to represent our performer:
- public class Percussionist implements Performer
- {
- private Instrument _instrument;
- @Override
- public void Perform() throws PerformaceException
- {
-
- _instrument.Play();
- }
- public void setInstrument(Instrument instrument)
- {
- _instrument = instrument;
- }
- }
The class represents a percussionist who plays the instrument injected to it from the setter method; well all looks good but we need the instrument which Shaun would be playing:
- public class Drums implements Instrument
- {
- @Override
- public void Play()
- {
-
- System.out.println("Playing Drums : ....");
- }
- }
As you can see we have drums which implement the instrument interface and we need this set up in the bean configuration file, so the Spring framework can identify it:
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
- <bean id="mike" class="spring.decoded.big.awards.Juggler">
- <constructor-arg value="10" />
- </bean>
-
- <bean id="bestOfMe" class="spring.decoded.big.awards.Singer" />
- <bean id="john" class="spring.decoded.big.awards.SingingJuggler">
- <constructor-arg value="11" />
- <constructor-arg ref="bestOfMe"/>
- </bean>
- <bean id="drum" class="spring.decoded.big.awards.Drums" />
- <bean id="shaun" class="spring.decoded.big.awards.Percussionist">
- <property name="instrument" ref="drum" />
- </bean>
- <bean id="bigAwardsStage"
- class="spring.decoded.big.awards.Stage"
- factory-method="getIstance" />
- </beans>
Notice that we have declared the percussionist too in the bean file, and instead of a constructor-arg attribute we have a property attribute to inject the dependency, what that bean declaration says is that:
"For the property whose name is instrument in the class Percussionist, set it with a reference drum declared in the bean configuration file above". Well, all we need now is to get the instance of this class and invoke the right method which is perform in this case to set the show on fire: In our PopularTalentShow.java class get these lines:
- public class PopularTalentShow
- {
-
-
-
-
- public static void main(String[] args) throws PerformaceException
- {
-
- System.out.println("Starting the show....");
-
- ApplicationContext context = new ClassPathXmlApplicationContext("spring/decoded/big/awards/big-awards.xml");
- Performer performer = (Performer)context.getBean("mike");
- if(!PrePerformaceChecks(performer, "Mike"))
- return;
- performer.Perform();
- System.out.println("Moving onto next performance : ");
-
- performer = (Performer)context.getBean("john");
- if(!PrePerformaceChecks(performer, "John"))
- return;
- performer.Perform();
- System.out.println("Moving onto next performance : ");
- performer = (Performer)context.getBean("shaun");
-
- if(!PrePerformaceChecks(performer, "Shaun"))
- return;
- performer.Perform();
- }
- private static Boolean PrePerformaceChecks(Performer performer, String performerName)
- {
- if(performer == null)
- {
- System.out.println(performerName + " is missing from the show...");
- return false;
- }
- return true;
- }
- }
Run the class and you should see it:
Feature of Java Spring framework
Here, we will look at another really useful feature from the Java Spring framework. There are occasions when you want to perform some initialization tasks in your class before the instance of it is ready to be consumed or used by anyone and also cleanup the resources of that class when done using it; as in:
- public class Juggler implements Performer {
- private int _ballCount = 5;
- public Juggler(){
- }
- public Juggler(int ballCount){
- _ballCount = ballCount;
- }
- public void Initialize(){
- System.out.println("Juggler: Registering in the show.");
- }
- public void Destroy(){
- System.out.println("Juggler: Signing off from the show.");
- }
- @Override
- public void Perform() throws PerformaceException {
-
- System.out.println("JUGGLING " + _ballCount + " BALLS");
- }
- }
So as you notice, before any performer in the show can perform, he needs to register into the show, so that is the first most important task that he should do before he can show his talent.
To do that, we need to use the Initialize() method; but wait, someone needs to invoke that method to make the Juggler eligible for the show. The first possibilty that occurs to us is to either invoke that method in our main method or have a Bootstrap class which does the job of invoking the initialize methods of all the beans.
Such a way would be very tedious and the list of such invokes would keep increasing and hence the maintainability of such code becomes very difficult.
Here comes Spring again to our rescue, wherein in my bean configuration file, I can ask Spring to perform initialization of my bean once the Spring context is created, as in:
- <bean id="mike" class="spring.decoded.big.awards.Juggler" init-method="Initialize" destroy-method="Destroy">
- <constructor-arg value="10" />
- </bean>
Notice that the init-method and destroy-method attributes specified with the bean declaration tells Spring to invoke the Initialize method of the bean once it is instantiated and destroy-method once the Spring context is closed or disposed of.
Let us see a working example of this. I have made changes to the PopularTalentShow::main(..) method and it should look something like this now:
- public static void main(String[] args) throws PerformaceException {
-
- System.out.println("Starting the show....");
- ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/decoded/big/awards/big-awards.xml");
- Performer performer = (Performer) context.getBean("mike");
- if (!PrePerformaceChecks(performer, "Mike"))
- return;
- performer.Perform();
- System.out.println("\nMoving onto the next performance");
- performer = (Performer) context.getBean("john");
- if (!PrePerformaceChecks(performer, "John"))
- return;
- performer.Perform();
- System.out.println("\nMoving onto the next performance");
- performer = (Performer) context.getBean("shaun");
- if (!PrePerformaceChecks(performer, "Shaun"))
- return;
- performer.Perform();
- System.out.println("\nShow is over.");
- context.close();
- }
Notice the context.close() call which would invoke the destroy-method on all the beans specified in our bean declaration file and perform the cleanup task, now if you run the application:
Notice the initialization stuff happening in the beginning, and the cleanup being performed in the end, the hefty job being delegated to Spring with just little or no effort.
Inject a dependency which is a collection
So far we have covered the setting of the expectations of the classes using constructor injection or the setter injections, and we saw how we can set a single bean expectation. What if you want to inject a dependency which is a collection? Well, Java Spring lets you do that with collection elements of Spring:
- <list> : Helps you setup injection of list of values, allowing duplication of values
- <set> : Helps you setup injection of set of values, ensuring distinct (i.e. no duplication) values
- <map> : Helps you setup injection of name-value pairs, name and value can be of any type.
- <props> : Helps you setup injection of name-value pairs, name and value both should be of type String only.
In our "Popular Talent Show" we have a performer who can play more than one instrument at the same time so let us see how we can implement this:
- public class BandMan implements Performer {
- private Collection<Instrument> _instrumentList;
- public void Initialize(){
- System.out.println("One Man Band: Registering in the show.");
- }
- public void Destroy(){
- System.out.println("One Man Band: Signing off from the show.");
- }
- @Override
- public void Perform() throws PerformaceException {
-
- for(Instrument instrument : _instrumentList){
- instrument.Play();
- }
- }
- public void setInstruments(Collection<Instrument> instrumentList){
- _instrumentList = instrumentList;
- }
- }
We have created a new class which would represent our one-man-band army. It has nothing special, just a collection set using the setter method, and in the interface implementation we iterate over the available instruments and invoke the play method on it.
Now our performer would need multiple instruments to play at the same time, so let us go ahead and create a "Flute" instrument for our performer using the "Drum" instrument that is already available:
- public class Flute implements Instrument {
- @Override
- public void Play() {
-
- System.out.println("Playing Flute : ....");
- }
- }
No magic so far. Next what we need is to declare our performer in the bean configuration file:
- <bean id="flute" class="spring.decoded.instruments.Flute">
- </bean>
- <bean id="edward" class="spring.decoded.talent.show.BandMan" init-method="Initialize" destroy-method="Destroy">
- <property name="instruments">
- <list>
- <ref bean="drum"/>
- <ref bean="guitar"/>
- </list>
- </property>
- </bean>
Notice the bean declaration, that's the important place to focus on and make use of the collection elements of the Spring framework. We have used the list element and given it the references to the two beans, one drum and the other flute.
That's all we need to inject the list into the band man class (or bean), and we need to invoke this into the main method just as we did for other beans. Run the application and you should see something like this:
Well, this was as simple as it could be. You can play around with the other collection elements which I mentioned in the beginning of the article, you just need to change the list element to any of the other three elements and set the values appropriately. In the case of name-value pairs:
- <bean id="edward" class="spring.decoded.talent.show.BandMan" init-method="Initialize" destroy-method="Destroy">
- <property name="instruments">
- <map>
- <entry key="Fute" value-ref="flute" />
- <entry key="Drums" value-ref="drum" />
- </map>
- </property>
- </bean>
And the private member to hold the collection in the BandMan class should be:
- private Map<String, Instrument> _instrumentMap;
It's so simple and easy, without any hassles. That is it for this article, we will see some more action in future chapters, until then enjoy.