^ Click Here

Thursday, March 29, 2012

get a random element from Set or Map

To get a random element from a list is quite easy......you just have to get the element t the nth position where n is a random number. But A Set is an unordered collection so there is no question of any definite element at definite position.

In this situation the way to get a random element from a Set might not have a straightforward way.......But the thing that can be done is iterate through the set and get the nth element where n is a random number. Conceptually it's the same as getting a random element from a List or array.


public String getRandomId(Set<String> idSet){
  int Size = idSet.size();
  int item = new Random().nextInt(Size);
  return (String) idSet.toArray()[item];
 }

 
Above method will return a random String from a Set of String........

Now suppose there is a Map with a String type as key and anything else say an Object as value...for example


Map<String,User> userMap = new HashMap<String,User>();

where User  is a Class and userMap holds the map between String id as key and user object as value.......to get a random user from this map we will use the above method in the example


String randomId = this.getRandomId(userMap.keySet());
User randomUser = userMap.get(randomId);

Hence we can get a random elements through this method. we just got a set of String of keys of the map and then used the previous getRandomId method to get a random key and got the corresponding value from the map.

Hope it helps.....

Saturday, March 17, 2012

Autowiring with annotation and autodiscovering Example

We have seen the examples where Autowiring (with .xml) was done. It's sort of magical comprehensibility of Spring Framework where it by itself chooses the proper candidate and connect it to the respective beans

In last example it was autowiring with configuration in xml file, Now we will see it with annotation and autodiscovering. Autodiscovering is meant to be the setting where beans are auto discovered by Spring Framework through Classes and the annotations are used for setting the value and autowiring.

I made a package named "annotationAutowire" and inside that I put the same Classes which were there in the previous example of Spring Basic. The only difference that this time the classes are annotated.

the Class Person.java

package annotationAutowire;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class Person {
 @Value("Rahul")
 private String name;
 private IAnimal animal;
 
 public void setName(String name) {
  this.name = name;
 }
 public String getName() {
  return name;
 }
 public IAnimal getAnimal() {
  return animal;
 }
 @Autowired
 @Qualifier("dog")
 public void setAnimal(IAnimal animal) {
  this.animal = animal;
 }
 public String toString() {
  return name+" has a "+animal.toString();
 }
}


the interface IAnimal.java

package annotationAutowire;

public interface IAnimal {
 public void play();
}

the Class Dog.java

package annotationAutowire;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class Dog implements IAnimal {
 @Value("Doug")
 private String name;
 public void play() {
  // TODO Auto-generated method stub
  System.out.println("Playing with "+name);
 }
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public String toString() {
  return " Dog with name "+name;
 }
}

the Class Cat.java

package annotationAutowire;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class Cat implements IAnimal {
 
 private String name;
 public void play() {
  // TODO Auto-generated method stub
  System.out.println("Playing with "+name);
 }
 public String getName() {
  return name;
 }
 @Value("jejebel")
 public void setName(String name) {
  this.name = name;
 }
 public String toString() {
  return " Cat with name "+name;
 }
}


The annotation used are

@Component - use for declaring the instance of the class as bean, equivalent to bean tag in .xml file
@Autowired - declares that the element is autowired, equivalent to "autowire" attribute in xml file. The autowiring rules are unchanged. It could be placed at the declaration in the class as well as at the setter method.
@Qualifier - this annotation is used to tell that which component would qualify for autowiring, It can be related to autowire-candidate attribute in .xml file. it's safe to provide one to help in avoiding later conflicts.
@Value - this annotation is used to pass the value as String, it is the equivalent of property and p namespace equivalent in .xml file and can be placed at declaration as well as at setter method.

the config.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 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/context         
         http://www.springframework.org/schema/context/spring-context-3.0.xsd">


<context:component-scan base-package="annotationAutowire"></context:component-scan>
</beans>


the context:component-scan is used for autodiscovering it will discover all the component (through @Component annotation) in the explicitly directed base-package annotationAutowire and while creating bean through those component it will do the job of autowiring with the help of @Autowired and @Qualifier annotations
Hence like earlier examples we didn't need to define bean and pass the values through property and p namespace. This all was taken care by annotations.
Element : component-scan
Scans the classpath for annotated components that will be auto- registered as Spring beans. By default, the Spring-provided @Component, @Repository, @Service, and @Controller stereotypes will be detected. Note: This tag implies the effects of the 'annotation-config' tag, activating @Required, @Autowired, @PostConstruct, @PreDestroy, @Resource, @PersistenceContext and @PersistenceUnit annotations in the component classes, which is usually desired for autodetected components (without external configuration). Turn off the 'annotation-config' attribute to deactivate this default behavior, for example in order to use custom BeanPostProcessor definitions for handling those annotations. Note: You may use placeholders in package paths, but only resolved against system properties (analogous to resource paths). A component scan results in new bean definition being registered; Spring's PropertyPlaceholderConfigurer will apply to those bean definitions just like to regular bean definitions, but it won't apply to the component scan settings themselves.
Content Model : (include-filter*, exclude-filter*)

the test Class PersonTest.java

package pkg;

import annotationAutowire.Person;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class PersonTest {
 @Test
 public void vehicleTest(){
  ApplicationContext context = new ClassPathXmlApplicationContext("config.xml");
  Person person = (Person) context.getBean("person");
  System.out.println(person);
 }
}

The Structure finally is


junit test result without doubt should be "Rahul has a  Dog with name Doug". because the qualifier is set to "dog".......and it can be changed to "cat" to get the autowiring of animal with cat component/bean.

Hope it helps.
 

Thursday, March 15, 2012

Spring Autowiring types with examples

 [ All the examples in this post are basically an extension from the previous post of Spring Basic ]

Autowiring is a feature in Spring through which we can pass the reference of any dependent bean automatically.......This is a step where we are telling the Spring framework to take care of the dependencies.
In that case when Application Context is created the Spring Framework will search for the beans on which it is dependent on according to set guidelines and if and when it finds the bean it will inject that automatically hence we no further need to take care of passing the reference.
Controls whether bean properties are "autowired". This is an automagical process in which bean references don't need to be coded explicitly in the XML bean definition file, but rather the Spring container works out dependencies. There are 4 modes: 1. "no" The traditional Spring default. No automagical wiring. Bean references must be defined in the XML file via the element (or "ref" attribute). We recommend this in most cases as it makes documentation more explicit. Note that this default mode also allows for annotation- driven autowiring, if activated. "no" refers to externally driven autowiring only, not affecting any autowiring demands that the bean class itself expresses. 2. "byName" Autowiring by property name. If a bean of class Cat exposes a "dog" property, Spring will try to set this to the value of the bean "dog" in the current container. If there is no matching bean by name, nothing special happens. 3. "byType" Autowiring if there is exactly one bean of the property type in the container. If there is more than one, a fatal error is raised, and you cannot use byType autowiring for that bean. If there is none, nothing special happens. 4. "constructor" Analogous to "byType" for constructor arguments. If there is not exactly one bean of the constructor argument type in the bean factory, a fatal error is raised. Note that explicit dependencies, i.e. "property" and "constructor-arg" elements, always override autowiring. Note: This attribute will not be inherited by child bean definitions. Hence, it needs to be specified per concrete bean definition

What did I mean by "set guidelines"?? for Spring Framework to find the correct bean we must set some rules.............well nothing speaks better than example....Hence going with our previous example

Our config.xml file will be

<beans xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemalocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
         http://www.springframework.org/schema/context         
         http://www.springframework.org/schema/context/spring-context-3.0.xsd">


<bean class="pkg.Person" id="person" p:name="Rahul" autowire="byType">   
</bean>
<bean class="pkg.Dog" id="Dog" p:name="Doug" autowire-candidate="false"></bean>
<bean class="pkg.Cat" id="Cat" p:name="Jejebel"> 
 </bean></beans>
Note that the autowiring is "byType" , it simply means in the Person Class the type of "animal" is IAnimal......Hence the Spring framework in the Application Context will search for all beans with type IAnimal and will inject(connect) it to the animal and hence it's autowired. We don't need to explicitly pass the reference of any bean for animal property as in Spring Basic Example.

Now the question arises what if it finds more than one bean which have type IAnimal as in our case "Dog" and "Cat" both are of type IAnimal.........It certainly would throw an error due to indecision for which bean to use something like - "org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'person' defined in class path resource [config.xml]: Unsatisfied dependency expressed through bean property 'animal': : No unique bean of type [pkg.IAnimal] is defined: expected single matching bean but found 2: [Dog, Cat]; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [pkg.IAnimal] is defined: expected single matching bean but found 2: [Dog, Cat]".

If we would have used byName this problem won't have been there since two beans can't have same name(id) more on it later.........but we are not using that.
the solution is using an autowire-candidate property on beans as the bean "Dog" have autowire-candidate as false which simply means that this bean is not available for autowiring that simply means that only bean "Cat" is available for autowiring.
Indicates whether or not this bean should be considered when looking for matching candidates to satisfy another bean's autowiring requirements. Note that this does not affect explicit references by name, which will get resolved even if the specified bean is not marked as an autowire candidate.

Now when we run our test class it will give an output "Rahul has a  Cat with name Jejebel" 

It could be tedious to provide the kind of autowire for many beans specially when you are following a definite norm.......like you want all the beans to be autowired with "byName". Spring has provided the facility, all you need to do is in the configuration xml file set the default autowire as "byName". point to keep in mind that it will only work for one configuration file (you can have multiple) and not for the full application context. So you can organize all your same type autowired bean in one configuration file and set the default for that very xml file

test will again give you the same result .

But what If you need to have a default-autowire as "byType" in your configuration file but there are a few exceptions which needs to be autowired as "byName". Well in that case you can override the default autowiring just by specifically declaring it for the respective bean as "byName".

<beans xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemalocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
         http://www.springframework.org/schema/context         
         http://www.springframework.org/schema/context/spring-context-3.0.xsd"
          default-autowire="byType">
   
<bean class="pkg.Person" id="person" p:name="Rahul">  
</bean>
<bean class="pkg.Dog" id="Dog" p:name="Doug" autowire-candidate="false"></bean>
<bean class="pkg.Cat" id="Cat" p:name="Jejebel">
</bean></beans>

Not just that you still can use the (older style) property with ref attribute for passing the dependency even if you are using an autowire tag on it. Hence its flexible.

Let's talk about the kind of autowiring

What we saw in the earlier example was "byType". have a look at the whole bunch :-

 > no - no autowiring should be done on the particular bean and the dependency
must be passed explicitly through "ref" attribute.

 > byNameAttempts to match all properties of the autowired bean with beans
that have the same name (or ID) as the properties. Properties for which there’s
no matching bean will remain unwired.

 > byTypeAttempts to match all properties of the autowired bean with beans
whose types are assignable to the properties. Properties for which there’s no
matching bean will remain unwired.

 > constructorTries to match up a constructor of the autowired bean with
beans whose types are assignable to the constructor arguments.

 > autodetectAttempts to apply constructor autowiring first. If that fails,
byType will be tried.


We have already seen the example of autowire as "byType"

now let's see an example with autowire equal to "byName"

<beans xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemalocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
         http://www.springframework.org/schema/context         
         http://www.springframework.org/schema/context/spring-context-3.0.xsd">


<bean class="pkg.Person" id="person" p:name="Rahul" autowire="byName">  
</bean>
<bean class="pkg.Dog" id="animal" p:name="Doug"></bean>
<bean class="pkg.Cat" id="Cat" p:name="Jejebel">
</bean></beans>

run the test again and it will output "Rahul has a  Dog with name Doug".

Thing to notice is that the name of bean "Dog" has been changed to "animal" on purpose, this way the the IAnimal type "animal" variable of class Person is mapped with the bean named "animal" and hence the dependency is autowired by Spring Framework according to the name.

Hence when the application context is created the framework search for the bean named "animal" and inject it into the bean "person" since the autowiring is "byName"

Now let's see the autowiring by constructor......to display this I would need to alter the class as I need to add a constructor to the Person class

the Person Class

public class Person {
 private String name;
 private IAnimal animal;
 
 public Person(IAnimal animal) {
  this.animal = animal;
 }
 public void setName(String name) {
  this.name = name;
 }
 public String getName() {
  return name;
 }
 public IAnimal getAnimal() {
  return animal;
 }
 public String toString() {
  // TODO Auto-generated method stub
  return name+" has a "+animal.toString();
 }

changes are that there are no setter for IAnimal type animal.......instead it is set with the constructor.....in the constructor the reference is passed as an argument.

config.xml

<beans xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemalocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
         http://www.springframework.org/schema/context         
         http://www.springframework.org/schema/context/spring-context-3.0.xsd">


<bean class="pkg.Person" id="person" p:name="Rahul" autowire="constructor">  
</bean>
<bean class="pkg.Dog" id="Dog" p:name="Doug" autowire-candidate="false"></bean>

<bean class="pkg.Cat" id="Cat" p:name="Jejebel">
</bean></beans>

Run the test and it will print "Rahul has a  Cat with name Jejebel".

Hence it is clear that when autowire is constructor.......Spring framework will search for the constructor with argument type as IAnimal and then will search for the bean type "IAnimal" and then passes that bean to set animal.

autowire-candidate="false" is used for the same reason as for it was used in autowire byType.

I am not providing any example of autowire as "autodetect" since this is nothing but a combination of autowire by constructor and byType respectively i.e. it looks for constructor with argument type and if there is none it looks for the type and searches the bean accordingly.


Well this is not all.....we still have "autowire with annotation" and autodiscover features....................but that in other post......

Thursday, March 8, 2012

Sticky columns/headers (Freeze pane) in tables through jQuery

Many times you have seen that the columns or headers freezes when you scroll horizontally or vertically respectively in a table. It looks rather cool but more than that its very useful hence nowhere you loses the track on any cell as which column and which header it belongs to irrespective of where the cell is in large table.
Let's see what can be done

the css


#resultTable{
    width:1000px;
    height:500px;
    clear:both;
    overflow:auto;
    position:relative;
}
.sticky-col-table{
    background-color: #eee;
    margin-left:0px !important;
}
.sticky-row-table {
    background-color: #eee;
    margin-top:0px !important;
}

.scrollTable{

    border:1px solid red;
    margin-top:5px;
    text-align:center;
}
.scrollTable td,.scrollTable th{
    width:60px;
    padding:5px;
    border:1px solid green;
}
now in the body let's put this structure


<div id="condDiv">
Columns : <input type="text" id="inputColumn" value="50"/> <br />
Rows : <input type="text" id="inputRow" value="50"/><br />
<input type="button" value="Create Table" onclick="return val_table();"/>
</div><br />
<div id="resultTable"  onscroll="movestickyColumn(this)">
<div id="sticky-column" style="position:absolute;display:none;"> </div>
<div id="sticky-row" style="position:absolute;display:none;"> </div>
</div>
let me describe it a bit in condDiv div I have two input elements where a person can provide the number of rows and columns for creating a dynamic table by clicking on the create Table button

the resultTable div is the div which will hold the dynamic table created and on scrolling of the div the function movestickyColumn(this) is called with passing the div object to it.

also note that it holds two empty and hidden div sticky-column and sticky-row (idea is to hold the frozen part of table in these divs).

Now the script part one by one, first for creating dynamic table we will have functions as follow

 validations -


function val_table(){
    var row= $('#condDiv #inputRow').val();
    var column = $('#condDiv #inputColumn').val();
    if(typeof row == "undefined" || row == null || row == "" || row <= 0 || isNaN(row) || typeof column == "undefined" || column == null || column == "" || column <= 0 || isNaN(column)){
        alert("Please provide valid positive value for rows and columns");
        return false;
        }
    else if(row>500 || column>500){
        alert("The column or row can not be more than 500");
        return false;
    }
    else{
        if($("#resultTable #myTable").length > 0){
            $("#resultTable #myTable").remove();
            }
        $("#resultTable").append(create_table(column,row));
        stickyColumnNew(2);
        stickyRow();
        }
}

first of all I am validating the number of row and columns provided in the input field, if it is I am calling three functions

for creating table


function create_table(column,row){
    var tableArray = [];
  
    var tableHead = [];
    var tableBody = [];
    tableHead.push("<thead><tr>");
    tableBody.push("<tbody>");
    var count = 0;
    for(ro=0; ro<row; ro++){  
        tableBody.push("<tr>");
            for(col=0; col<column; col++){
                if(ro==0){
                        tableHead.push("<th>Head "+(col+1)+"</th>")
                    }
                if((count%column) == 0){
                tableBody.push("<td> cell-"+(count+1)+" row-"+(ro+1)+"</td>");
                }
                else{
                    tableBody.push("<td> cell-"+(count+1)+"</td>");
                    }
                    count++;
                }
        }
    tableHead.push("</tr></thead>");
    tableBody.push("</tbody>");
    tableArray.push("<table id='myTable' class='scrollTable'>"+tableHead.join("")+tableBody.join("")+"</table>");
    return tableArray.join("");
}

then for getting the frozen columns to be formed in the sticky-column div, function stickyColumnNew(2) is called. note that I am passing 2 as an argument to freeze first 2 columns, you can pass more or less.


function stickyColumnNew(col) {
    $("#sticky-column").html('');
    // var trlength = $('table.table_sorter tbody tr').length;      
    var documentFragment =[];
    documentFragment.push('<table class="sticky-col-table scrollTable">');
    var docHead = [];
    docHead.push("<thead><tr>");
    var docBody = [];
    docBody.push("<tbody>")
    var count = 0;
    $("#myTable thead tr th").each(function(){
        if(count < col){
        docHead.push("<th style='height:"+$(this).outerHeight()+";'>"+$(this).html()+"</th>");  //use outerHeight() to get the height with padding, border and margin
        }
        count++;
    });
    docHead.push("</tr></thead>");
    $("#myTable tbody tr").each(function(){
    docBody.push("<tr>")
        if(col >= 1){
            docBody.push("<td style='height:"+$(this).find('td:first').outerHeight()+";'>"+$(this).find('td:first').html()+"</td>");
        }
        if(col >= 2){
        for(val=2; val<=col; val++){
            docBody.push("<td>"+$(this).find('td:nth-child('+val+')').html()+"</td>");
            }
        }
        docBody.push("</tr>")
    });
    docBody.push("</tbody>");
    documentFragment.push(docHead.join("")+docBody.join("")+'</table>');
    $("#sticky-column").append(documentFragment.join(''));  
    }

Basically I am creating a dummy table with only the 2 columns I have to freeze, It's cell should have the same height and content as the original table and I am simply putting that table in sticky-column div

In the same fashion I will create the table with dummy header with function stickyRow


function stickyRow() {
    $("#sticky-row").html('');
    // var trlength = $('table.table_sorter tbody tr').length;      
    var documentFragment =[];
    documentFragment.push('<table class="sticky-row-table scrollTable">');
    var docHead = [];
    docHead.push("<thead><tr>");
    $("#myTable thead tr th").each(function(){
      
        docHead.push("<th style='height:"+$(this).outerHeight()+";'><div style='width:"+$(this).width()+";'>"+$(this).html()+"</div></th>");  //use outerHeight() to get the height with padding, border and margin
      
    });
    docHead.push("</tr></thead>");
    documentFragment.push(docHead.join("")+'</table>');
    $("#sticky-row").append(documentFragment.join(''));
    }

Now the only part left is the movestickyColumn on the div


function movestickyColumn(tableDiv) {
    posX = tableDiv.scrollLeft;
    posY = tableDiv.scrollTop;
    if(posX > 50) {
        $('table.sticky-col-table,#sticky-column').css('display','block');
        $('table.sticky-col-table,#sticky-column').css('left',posX+'px');
    }
    else{
        $('table.sticky-col-table,#sticky-column').css('display','none');
        }
      
    if(posY > 50){
    console.log(posY);
        $('table.sticky-row-table,#sticky-row').css('display','block');
        $('table.sticky-row-table,#sticky-row').css('top',posY+'px');
    }
    else{
        $('table.sticky-row-table,#sticky-row').css('display','none');
    }  
}

So actually I am checking that as soon as the vertical or horizontal scroll crosses the 50px margin I am displaying the sticky-row and sticky-column divs respectively and accordingly.

feel free to play, customize or enhance upon it

hope it helps.

Try it here : -

[As far as I have checked there is some problem as in firefox header row width is not aligned and in chrome the columns height are not aligned. I guess some conflict with blogger css and css I am using. Trying to find the solution. However independently I have checked in both browser as working fine.]  



Columns :
Rows :

Wednesday, March 7, 2012

getting the HTML tags on jsp from a variable without turning into special characters

While working today I came across a strange situation.......

the requirement was something like I have to dynamically get some html elements and contents and put them in a variable which then I was supposed to put in a .jsp file.

It had to be dynamic so that the jsp would render different in different condition. Everything was working okay as supposed to but the dynamic HTML element which I was getting in String format was coming in such a way that it turned all the HTML tags in special characters.

i.e. <br /> was coming like &lt;br /&gt;, So eventually while getting rendered in jsp page instead of it being a hypertext it was actually special characters and in browser all the tags were visible.

Hence if in my jsp if there is
<div id="fixedDiv">
<b>Try this</b>
<c:out value="${myHtml}" />
</div>

and in my java code if there was -

String myHtmlVal = "<div id="variableDiv"><p><input type="text"/>Fill Something</p></div>";
response.add("myHtml",myHtmlVal);

then on browser it was showing this instead of proper rendering of hypertext tags -

Try this
<div id="variableDiv"><p><input type="text"/>Fill Something</p></div>

this was because the c:out was giving the value as-

&lt;div id="variableDiv"&gt;&lt;p&gt;&lt;input type="text"\/&gt;Fill Something&lt;\/p&gt;&lt;/div&gt;

Someone told me that I need to get it encoded and then decoded by url encoder or something but it was only getting more weird.......

However the help was here

after sometime what actually worked was this -

String myHtmlVal = "<div id="variableDiv"><p><input type="text"/>Fill Something</p></div>";
response.add("myHtml",StringEscapeUtils.unescapeHtml(myHtmlVal));

this unescapeHtml helped in preserving the hypertext values from turning into special character.

Also note that in the reverse case if you have to show the tags on browser but instead it's working as hypertext you can achieve it by StringEscapeUtils.escapeHtml(myHtmlVal); method.

Hope it helps

Saturday, March 3, 2012

Spring p:namespace example

Continuing with what we learnt in the Spring Basic we will move on to other functionality

for now our example would be same as the basic example i.e.

Person.java
IAnimal.java
Dog.java
Cat.java

Now we will see the p:namespace option in the Spring config file config.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:p="http://www.springframework.org/schema/p"     <!-- This line is required for p:namespace to work -->
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    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/context         
         http://www.springframework.org/schema/context/spring-context-3.0.xsd">

<bean id="person" class="pkg.Person" p:name="Rahul"> 
    <property name="animal" ref="Dog"/>    
</bean>

<bean id="Dog" class="pkg.Dog" p:name="Doug"/>
<bean id="Cat" class="pkg.Cat" p:name="Jejebel"/>

</beans>

If we run the test now it will print the same "Rahul has a Dog with name Doug"....So as you can see the third line initializes the p namespace function through which we get rid of extra property tag in .xml which made the file heavy.
as for p namespace does the same thing which property tag does, it passes the value to the setter method and it's more readable.

To make it more clear if the Person class has an integer age property, then we can pass avalue through p namespace as p:age="32"

But unfortunately we can't pass reference through p namespace. Hence still where we need to pass the reference we are passing other bean we still have to go with property tag.

Do we have anything where we can pass the reference to other bean without property tag?
The answer fortunately is "Yes" however that's a totally unique functionality and hence much more important than p namespace, It's called "Autowiring"