Sunday, January 11, 2015

No separate schema definition for p-namespace and c-namespace.



  1. p-namesapce (Parameter namespace)
  2. c-namespace (Constructor namespace)

p-namesapce (Parameter namespace)

p-namespace simplifies the setter-based dependency injection code by enabling you to use the parameters to be injected as attributes of bean definition instead of the nested <property> elements.

<?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="addr1" class="com.ixi.samples.spring.cpns.Address">
        <property name="houseNo" value="2106"/>
        <property name="street" value="Newbury St"/>
        <property name="city" value="Boston"/>
        <property name="zipCode" value="02115-2703"/>
    </bean>
    <bean id="constArgAnotherBean" class="com.pfl.samples.spring.cpns.Person">
        <property name="firstName" value="Joe"/>
        <property name="lastName" value="John"/>
        <property name="age" value="35"/>
        <property name="address" ref="addr1"/>
    </bean>
</beans> 

with p-namespace, you can write this as:
<?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:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean name="addr1" class="com.ixi.samples.spring.cpns.Address" 
             p:houseNo="2106" 
             p:street="Newbury St" 
            p:city="Boston" 
            p:zipCode="02115-2703"/>
    <bean name="person1" class="com.ixi.samples.spring.cpns.Person" 
            p:firstName="Joe" 
            p:lastName="John" 
            p:age="35" 
           p:address-ref="addr1"/>     
</beans>  

It is simple! All you need to do is

  1. Add the p namespace URI (xmlns:p="http://www.springframework.org/schema/p") at the configuration xml with namespace prefix p. Please note that it is not mandatory that you should use the prefix p, you can use your own sweet namespace prefix :)
  2. For each nested property tag, add an attribute at the bean with name having a format of p:<property-name> and set attribute value to the value specified in the nested property element.
  3. If one of your property is expecting another bean, then you should suffix -ref to your property name while constructing the attribute name to use in bean definition. For eg, if you property name is address then you should use attribute name as address-ref

c-namespace (Constructor namespace)

c-namespace is similar to p-namespace but used with constructor-based dependency injection code. It simplifies the constructor-based injection code by enabling you to use the constructor arguments as attributes of bean definition rather than the nested <constructor-arg> elements.

<?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="addr1" class="com.pfl.samples.spring.cpns.Address">
  <constructor-arg name="houseNo" value="2106"/>
  <constructor-arg name="street" value="Newbury St"/>
  <constructor-arg name="city" value="Boston"/>
  <constructor-arg name="zipCode" value="02115-2703"/>
 </bean>
 <bean id="constArgAnotherBean" class="com.pfl.samples.spring.cpns.Person">
  <constructor-arg name="firstName" value="Joe"/>
  <constructor-arg name="lastName" value="John"/>
  <constructor-arg name="age" value="35"/>
  <constructor-arg name="address" ref="addr1"/>
 </bean>  
</beans> 

and with c-namespace, it can be written as
<?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:c="http://www.springframework.org/schema/c"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean name="addr1" class="com.pfl.samples.spring.cpns.Address"
        c:houseNo="2106" c:street="Newbury St"
        c:city="Boston" c:zipCode="02115-2703"/>
    <bean name="person1" class="com.pfl.samples.spring.cpns.Person"
        c:firstName="Joe" c:lastName="John"
        c:age="35" c:address-ref="addr1"/>
</beans>    

It is same as p-namespace. All you need to do is
Add the c namespace URI (xmlns:c="http://www.springframework.org/schema/c") at the configuration xml with namespace prefix c. The prefix is not mandatory like p-namespace
For each nested constructor-arg eleemnt, add the attribute with name c:<argument-name> to the bean definition and set the actual argument value as attribute value.
If one of your constructor argument is expecting another bean, then you should suffix -ref to your argument name while constructing the attribute name to use in bean definition (like p-namespace). For eg, if you argument name is address then you should use address-ref

Well, the above code has an issue though. It is using the constructor argument names and that will be available only if the code is compiled with debug enabled which may not be the case with production code. So, you will have to use the index rather than the argument names. With index, we can rewrite the above code as follows.

<?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="addr1" class="com.pfl.samples.spring.cpns.Address">
        <constructor-arg index="0" value="2106"/>
        <constructor-arg index="1" value="Newbury St"/>
        <constructor-arg index="2" value="Boston"/>
        <constructor-arg index="3" value="02115-2703"/>
    </bean>
    <bean id="constArgAnotherBean" class="com.pfl.samples.spring.cpns.Person">
        <constructor-arg index="0" value="Joe"/>
        <constructor-arg index="1" value="John"/>
        <constructor-arg index="2" value="35"/>
        <constructor-arg index="3" ref="addr1"/>
    </bean>
</beans> 

With c-namespace:

<?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:c="http://www.springframework.org/schema/c" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean name="addr1" class="com.pfl.samples.spring.cpns.Address"
        c:_0="2106" c:_1="Newbury St"
        c:_2="Boston" c:_3="02115-2703"/>
    <bean name="person1" class="com.pfl.samples.spring.cpns.Person"
        c:_0="Joe" c:_1="John"
        c:_2="35" c:_3-ref="addr1"/>
</beans> 

You may notice that there is not much difference rather than using index in the place of argument name. Also, the index should be prefixed by _(underscore) to make it as a valid xml attribute name.

You can use both p-namespace and c-namespace in together in bean definition( see below):
<?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:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">     
    <bean name="person3" class="com.pfl.samples.spring.cpns.Person" 
         c:_0="Mary" 
         c:_1="Joe" 
         c:_2="30" 
         p:address-ref="address2"/>
</beans> 

You may also have noticed that there is no separate schema definition for p-namespace and c-namespace.

No comments:

Post a Comment