1. Hello World II (Application Context)

From book Spring Recipes.

Most basic Spring application: starts with simple beans, then adds lists as properties of the bean.

Ingredients:
1. JDK 1.6
2. Simplest version of Eclipse IDE for Java Develpoment
3. spring-framework-3.1.0.M1.zip

Make a Java project in eclipse.
make a folder in the root of the project
Unzip spring-framework-3.1.0.M1.zip
from ./dist/ directory you will need
org.springframework.asm-3.1.0.M1.jar
org.springframework.beans-3.1.0.M1.jar
org.springframework.context-3.1.0.M1.jar
org.springframework.core-3.1.0.M1.jar
org.springframework.expression-3.1.0.M1.jar
from ./projects/spring-build/lib/ivy/
commons-logging.jar



Make a bean class
package com.apress.springrecipes.sequence;
 
public class SequenceGenerator {
 
    private String prefix;
    private String suffix;
    private int initial;
    private int counter;
 
    public SequenceGenerator() {}
 
    public SequenceGenerator(String prefix, String suffix, int initial) {
        this.prefix = prefix;
        this.suffix = suffix;
        this.initial = initial;
    }
 
    public void setPrefix(String prefix) {
        this.prefix = prefix;
    }
 
    public void setSuffix(String suffix) {
        this.suffix = suffix;
    }
 
    public void setInitial(int initial) {
        this.initial = initial;
    }
    public synchronized String getSequence() {
        StringBuffer buffer = new StringBuffer();
        buffer.append(prefix);
        buffer.append(initial + counter++);
        buffer.append(suffix);
        return buffer.toString();
    }
}

Make a beans.xml file in the ./src/ directory of the project:
<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-3.0.xsd">

    <bean name="sequenceGenerator" class="com.apress.springrecipes.sequence.SequenceGenerator">
        <property name="prefix">
            <value>30</value>
        </property>

        <property name="suffix">
            <value>A</value>
        </property>
        <property name="initial">
            <value>100000</value>
        </property>
    </bean>

</beans>

Make a runner class to test if this spring project works.
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.apress.springrecipes.sequence.SequenceGenerator;


public class runner {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
 
        SequenceGenerator generator = (SequenceGenerator) context.getBean("sequenceGenerator");
 
        System.out.println(generator.getSequence());
        System.out.println(generator.getSequence());
    }
}

Run it, output:
Mar 29, 2011 11:19:24 AM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@145d068: startup date [Tue Mar 29 11:19:24 CDT 2011]; root of context hierarchy
Mar 29, 2011 11:19:24 AM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [beans.xml]
Mar 29, 2011 11:19:25 AM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@ce5b1c: defining beans [sequenceGenerator]; root of factory hierarchy
30100000A
30100001A

----------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------
You could also get the bean via constructor arguments
<bean name="sequenceGenerator"
    class="com.apress.springrecipes.sequence.SequenceGenerator">
    <constructor-arg>
        <value>30</value>
    </constructor-arg>

    <constructor-arg>
        <value>A</value>
    </constructor-arg>
    <constructor-arg>
        <value>100000</value>
    </constructor-arg>
</bean>
----------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------
You could also declare the bean using a shortcut format using the value attribute
<bean id="sequenceGenerator"
    class="com.apress.springrecipes.sequence.SequenceGenerator">
    <property name="prefix" value="30" />
    <property name="suffix" value="A" />
    <property name="initial" value="100000" />
</bean>
The same way for the constructor arguments
<bean name="sequenceGenerator"
    class="com.apress.springrecipes.sequence.SequenceGenerator">
    <constructor-arg value="30" />
    <constructor-arg value="A" />
    <constructor-arg value="100000" />
</bean>
----------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------
You could also declare the bean using attribute names for each field of the bean.
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
 
    <bean id="sequenceGenerator"
        class="com.apress.springrecipes.sequence.SequenceGenerator"
        p:prefix="30" p:suffix="A" p:initial="100000" />
</beans>


Add Collections

List(Array), Set

The elements allowed inside the <list> tag can be a simple constant value specified by <value>, a bean reference by <ref>, an inner bean definition by <bean>, an ID reference definition by <idref>, or a null element by <null>. You can even embed other collections in a
collection.

Modify the bean class to include a list (of suffices)
package com.apress.springrecipes.sequence;

import java.util.List;

public class SequenceGenerator {

    private String prefix;
    private List<Object> suffixes;
    private int initial;
    private int counter;

    public SequenceGenerator() {
    }

    public SequenceGenerator(String prefix, List<Object> suffixes, int initial) {
        this.prefix = "MMM";
        this.suffixes = suffixes;
        this.initial = initial;
    }

    public void setPrefix(String prefix) {
        this.prefix = prefix;
    }

    public void setSuffixes(List<Object> suffixes) {
        this.suffixes = suffixes;
    }


    public void setInitial(int initial) {
        this.initial = initial;
    }

    public synchronized String getSequence() {
        StringBuffer buffer = new StringBuffer();
        buffer.append(prefix);
        buffer.append(initial + counter++);
        for (Object suffix : suffixes) {
            buffer.append("-");
            buffer.append(suffix);
        }

        return buffer.toString();
    }
}


Modify the bean.xml
<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-3.0.xsd">

    <bean name="sequenceGenerator" class="com.apress.springrecipes.sequence.SequenceGenerator">
        <property name="prefix">
            <value>30</value>
        </property>
        <property name="suffixes">
            <list>
                <value>A</value>
                <bean class="java.net.URL"> 
//relates to the constructor of the URL(protocol, host,file)
                    <constructor-arg value="http" />
                    <constructor-arg value="www.apress.com" />
                    <constructor-arg value="/" />
                </bean>
                <null />
            </list>
        </property>

        <property name="initial">
            <value>100000</value>
        </property>
    </bean>

</beans>


If suffixes was an array of Objects instead: The definition of an array in the bean configuration file is identical to a list denoted by the <list> tag.
If suffixes was a set of Objects instead: The definition of an array in the bean configuration file should be declared using the <set> tag. Spring preserves the order of your elements by using java.util.LinkedHashSet,

Output is

Mar 29, 2011 1:10:36 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@145d068: startup date [Tue Mar 29 13:10:36 CDT 2011]; root of context hierarchy
Mar 29, 2011 1:10:36 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [beans.xml]
Mar 29, 2011 1:10:37 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1e8a1f6: defining beans [sequenceGenerator]; root of factory hierarchy
30100000-A-http://www.apress.com/-null
30100001-A-http://www.apress.com/-null

Map

package com.apress.springrecipes.sequence;
...
public class SequenceGenerator {
    ...
    private Map<Object, Object> suffixes;
 
    public void setSuffixes(Map<Object, Object> suffixes) {
        this.suffixes = suffixes;
    }

 
    public synchronized String getSequence() {
        StringBuffer buffer = new StringBuffer();
        ...
        for (Map.Entry entry : suffixes.entrySet()) {
            buffer.append("-");
            buffer.append(entry.getKey());
            buffer.append("@");
            buffer.append(entry.getValue());
        }

        return buffer.toString();
    }
}

bean.xml
 <bean id="sequenceGenerator"
    class="com.apress.springrecipes.sequence.SequenceGenerator">
    ...
    <property name="suffixes">
        <map>
            <entry key="type" value="A" />
            <entry key="url">
                <bean class="java.net.URL">
                    <constructor-arg value="http" />
                    <constructor-arg value="www.apress.com" />
                    <constructor-arg value="/" />
                </bean>
            </entry>
        </map>

    </property>
</bean>

Output:
Mar 29, 2011 1:45:45 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@145d068: startup date [Tue Mar 29 13:45:45 CDT 2011]; root of context hierarchy
Mar 29, 2011 1:45:45 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [beans.xml]
Mar 29, 2011 1:45:45 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@a3d4cf: defining beans [sequenceGenerator]; root of factory hierarchy
30100000-type@A-url@http://www.apress.com/
30100001-type@A-url@http://www.apress.com/


Nulled map value
<property name="nulledMapValue">
        <map>
            <entry>
                <key> <value>null</value> </key>
            </entry>
        </map>
    </property>

Properties : Maps that are always Strings
private Properties suffixes;
 
public void setSuffixes(Properties suffixes) {
        this.suffixes = suffixes;
    }

 <props>
            <prop key="type">A</prop>

            <prop key="url">http://www.apress.com/</prop>
            <prop key="null">null</prop>
  </props>


Declare Inheritance in bean.xml

bean.xml
<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-3.0.xsd">

     <bean id="baseSequenceGenerator"
        class="com.apress.springrecipes.sequence.SequenceGenerator">
        <property name="prefix" value="30" />
        <property name="initial" value="100000" />
        <property name="suffixes">
            <list>
                <value>A</value>
                <value>B</value>
            </list>
        </property>
    </bean>
   
    <bean id="sequenceGenerator" parent="baseSequenceGenerator">
        <property name="prefix" value="PRE" />
        <property name="suffixes">
            <list merge="true">
                <value>A</value>
                <value>C</value>
            </list>
        </property>
    </bean>

</beans>

Simple list-based sequence generator:
package com.apress.springrecipes.sequence;

import java.util.List;

public class SequenceGenerator {

    private String prefix;
    private List<Object> suffixes;
    private int initial;
    private int counter;

    public void setPrefix(String prefix) {
        this.prefix = prefix;
    }

    public void setSuffixes(List<Object> suffixes) {
        this.suffixes = suffixes;
    }

    public void setInitial(int initial) {
        this.initial = initial;
    }

    public synchronized String getSequence() {
        StringBuffer buffer = new StringBuffer();
        buffer.append(prefix);
        buffer.append(initial + counter++);
        for (Object suffix : suffixes) {
            buffer.append("-");
            buffer.append(suffix);
        }
        return buffer.toString();
    }
}
Output
30100000-A-B-A-C
30100001-A-B-A-C
Note:
1. The attributes of the parent will be inherited at the child, If they are not declared at the child (PRE has been over-written by the child)
2. Note that the bean class itself does not declare any inheritance
3. The content of the list will be appended (if it is a set instead, redundancies will be eliminated)

Object Instantiation

If there’s no <constructor-arg> element specified, the default constructor with no argument will be invoked. Then for each <property> element, Spring will inject the value through the setter method.
Otherwise, if there are one or more <constructor-arg> elements specified, Spring will invoke the most appropriate constructor that matches your arguments.
 <bean id="aaa" class="com.apress.springrecipes.shop.Battery">
        <constructor-arg value="AAA" />
        <constructor-arg value="2.5" />
        <property name="rechargeable" value="true" />
  </bean>
Equivalent to
Product aaa = new Battery("AAA", 2.5);
aaa.setRechargeable(true);

To avoid ambiguity over which constructor you intended to execute, use the optional attributes type and index for the <constructor-arg>.  There’s not a name attribute in <constructor-arg>, as constructor arguments are position-based.(at runtime there is no parameter name over method calls.)
<constructor-arg type="int" index="0" value="100000" />
<constructor-arg type="java.lang.String" index="1" value="A" />


Bean Reference Declaration

Example:
In case of the sequence number generator example, here we avoid using String as prefix and use an interface as a prefix generator:
package com.apress.springrecipes.sequence;  
public interface PrefixGenerator {  
    public String getPrefix();
}
Assume we use current date as the prefix generated:
package com.apress.springrecipes.sequence;
public class DatePrefixGenerator implements PrefixGenerator {
private DateFormat formatter;

    public void setPattern(String pattern) {
        this.formatter = new SimpleDateFormat(pattern);
    }
 
    public String getPrefix() {
        return formatter.format(new Date());
    }
}
Specify a bean reference for a bean property or a constructor argument
1. by the <ref> element.
bean.xml would have:
<bean id="datePrefixGenerator" class="com.apress.springrecipes.sequence.DatePrefixGenerator">
    <property name="pattern" value="yyyyMMdd" />
</bean>
<bean id="sequenceGenerator" class="com.apress.springrecipes.sequence.SequenceGenerator">
    <property name="initial" value="100000" />
    <property name="suffix" value="A" />
    <property name="prefixGenerator">
        <ref bean="datePrefixGenerator" />
    </property>
</bean>

local

The bean name in the <ref> element’s bean attribute can be a reference to any bean in the IoC container, even if it’s not defined in the same XML configuration file. If you are referring to a bean in the same XML file, you should use the local attribute, as it is an XML ID reference.
so:
<property name="prefixGenerator">
        <ref bean="datePrefixGenerator" />
</property>

--->
<property name="prefixGenerator">
        <ref local="datePrefixGenerator" />
</property>
OR  <property name="prefixGenerator" ref="datePrefixGenerator" />
Benefit of local: XML editors can be used to check the integrity (e.g. eclipse right click the XML document->Validate)
OR
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
 
    <bean id="sequenceGenerator"
        class="com.apress.springrecipes.sequence.SequenceGenerator"
        p:suffix="A" p:initial="1000000"
        p:prefixGenerator-ref="datePrefixGenerator" /> //suffix with ref
</beans>

2. Enclose a bean declaration as an inner bean inside the tag you need it.
<property name="prefixGenerator">    //or it could be <constructor-arg>
        <bean class="com.apress.springrecipes.sequence.DatePrefixGenerator">
            <property name="pattern" value="yyyyMMdd" />
        </bean>
</property>

Type


type attribute of single entities OR value-type attribute of the collection tag to specify the type for all elements in this collection OR  defined your collections in a type-safe way private List<Integer> suffixes;Spring will convert data from XML file itself to integers.
<list>
            <value>5</value>
            <value>10</value>
            <value>20</value>
</list>
 ---><list>
            <value type="int">5</value>
            <value type="int">10</value>
            <value type="int">20</value>
</list>

with List<Object> suffixes;
 OR<list value-type="int">
     <value>5</value>
     <value>10</value>
     <value>20</value>
</list>



then suffixes in the example could be  private List<Object> suffixes;












ċ
src-BeanInheritedList.rar
(1k)
Morteza Sh-,
Mar 30, 2011, 8:40 AM
ċ
src-BeanRef.rar
(2k)
Morteza Sh-,
Mar 30, 2011, 9:23 AM
ċ
srcWithMap.rar
(1k)
Morteza Sh-,
Mar 29, 2011, 11:47 AM
Comments