Saturday, May 29, 2010

Part V : A Simple and Smart Result Mapper

The examples so far only deal with single table. But it is very much possible to join multiple tables and still use this mapper. As an example consider three entities as shown below:
T_REPOSITORY
REPOSITORY_ID int
REPOSITORY_NAME varchar
CONNECTOR_ID int
T_CONNECTOR
CONNECTOR_ID int
CONNECTOR_NAME varchar
URL varchar
OWNER_ID int
T_OWNER
OWNER_ID int
OWNER_NAME varchar
OWNER_KEY varchar
The relationship is clear - a repository has a connector and a connector has a owner. So how can you populate a Repository object containing a Connector Object which in turn has an Owner object. This is just simple. Execute this query.
SELECT r.repository_id "repositoryId", r.repository_name "repositoryName",
c.connector_id "connector.connectorId",
c.connector_name "connector.connectorName",
c.url "connector.url",
o.owner_id "connector.owner.ownerId",
o.owner_name "connector.owner.ownerName",
o.owner_key "connector.owner.ownerKey"
FROM
t_repository r,t_connector c, t_owner o
WHERE
r.repository_id = ?
AND c.connector_id = r.connector_id
AND o.owner_id = c.owner_id


The mapper automatically checks if the child object exists, if not it creates one and then populates the properties. The Javabeans are listed below for reference.
Listing - Repository.java
import org.apache.commons.lang.builder.ToStringBuilder;
public class Repository {
private int repositoryId;
private String repositoryName;
private Connector connector;
/**
* @return the repositoryId
*/
public int getRepositoryId() {
return repositoryId;
}
/**
* @param repositoryId the repositoryId to set
*/
public void setRepositoryId(int repositoryId) {
this.repositoryId = repositoryId;
}
/**
* @return the repositoryName
*/
public String getRepositoryName() {
return repositoryName;
}
/**
* @param repositoryName the repositoryName to set
*/
public void setRepositoryName(String repositoryName) {
this.repositoryName = repositoryName;
}
/**
* @return the connector
*/
public Connector getConnector() {
return connector;
}
/**
* @param connector the connector to set
*/
public void setConnector(Connector connector) {
this.connector = connector;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {

return ToStringBuilder.reflectionToString(this);
}


}


Listing - Connector.java
import org.apache.commons.lang.builder.ToStringBuilder;
public class Connector {
private int connectorId;
private String connectorName;
private String url;
private Owner owner;
/**
* @return the connectorId
*/
public int getConnectorId() {
return connectorId;
}
/**
* @param connectorId the connectorId to set
*/
public void setConnectorId(int connectorId) {
this.connectorId = connectorId;
}
/**
* @return the connectorName
*/
public String getConnectorName() {
return connectorName;
}
/**
* @param connectorName the connectorName to set
*/
public void setConnectorName(String connectorName) {
this.connectorName = connectorName;
}
/**
* @return the url
*/
public String getUrl() {
return url;
}
/**
* @param url the url to set
*/
public void setUrl(String url) {
this.url = url;
}


/**
* @return the owner
*/
public Owner getOwner() {
return owner;
}
/**
* @param owner the owner to set
*/
public void setOwner(Owner owner) {
this.owner = owner;
}

/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {

return ToStringBuilder.reflectionToString(this);
}
}


Listing - Owner.java
import org.apache.commons.lang.builder.ToStringBuilder;


/**
* @author dhrubo
*
*/
public class Owner {
private long ownerId;
private String ownerName;
private String ownerKey;



/**
* @return the ownerId
*/
public long getOwnerId() {
return ownerId;
}



/**
* @param ownerId the ownerId to set
*/
public void setOwnerId(long ownerId) {
this.ownerId = ownerId;
}



/**
* @return the ownerName
*/
public String getOwnerName() {
return ownerName;
}



/**
* @param ownerName the ownerName to set
*/
public void setOwnerName(String ownerName) {
this.ownerName = ownerName;
}



/**
* @return the ownerKey
*/
public String getOwnerKey() {
return ownerKey;
}



/**
* @param ownerKey the ownerKey to set
*/
public void setOwnerKey(String ownerKey) {
this.ownerKey = ownerKey;
}



@Override
public String toString() {

return ToStringBuilder.reflectionToString(this);
}
}

Part IV : A Simple and Smart Result Mapper

In my last post, I have shown how the dao support class changed to convert list of maps to list of domain objects. Now the DAO implementation class must also change to use these new methods. Here is the modified DAO class.
Listing – UserDaoImpl.java
package net.sf.dms.security.dao.impl;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.sf.dms.security.dao.api.UserDao;
import net.sf.dms.security.domain.User;
import net.sf.spring.dao.AbstractBaseDaoSupport;

/**
* @author dhrubo
* 
*/
public class UserDaoImpl extends AbstractBaseDaoSupport implements UserDao {

private Logger logger = LoggerFactory.getLogger(UserDaoImpl.class);
@Override
public List<User> listUsers() {
return (List<User>)this.queryForList("listUsers", User.class);
}

@Override
public void save(User user) {
this.insert("saveUser", user.getEmail(),
user.getPassword(), user.getFirstName(), user.getLastName());
}

@Override
public void update(User user) {

}
@Override
public User findUserByUserName(String username) {
logger.debug("Loading user details as part of authentication");
return (User)this.queryForObject("findUserByUserName", User.class, username);  
}

@Override
public List<User> findUsersStartingWith(String nameStartsWith) {
return (List<User>)this.queryForList("findUsersStartingWith", User.class, nameStartsWith + "%");  
}
}


Now you can see clearly that the list or finder queries have been reduced to just 1 line. I guess this code reduction is same as in any ORM or datamapper. Now let us see how the SQL has changed. I have tested this code on Postgresql 8.3 and should work with any sensible database available.
<?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-3.0.xsd">

<bean id="secSqlMap" class="org.springframework.beans.factory.config.MapFactoryBean">
<property name="sourceMap">
<map>
<entry key="listUsers">
<value>
<![CDATA[
SELECT first_name "firstName",last_name "lastName",email "userCode",user_id "userId" FROM t_user

]]>

</value>

</entry>

<entry key="saveUser">
<value>
<![CDATA[
INSERT INTO t_user(user_id, email, password, first_name,last_name) VALUES (nextval('t_user_seq'), ?, ?, ?, ?)

]]>

</value>

</entry>

<entry key="findUserByUserName">
<value>
<![CDATA[
SELECT first_name "firstName",last_name "latName",email "userCode",user_id "userId" FROM t_user WHERE email = ?

]]>

</value>

</entry>

<entry key="findUsersStartingWith">
<value>
<![CDATA[
SELECT first_name "firstName",last_name "latName",email "userCode",user_id "userId" FROM t_user 
WHERE first_name LIKE ?;

]]>

</value>

</entry>

</map>


</property>
</bean>

</beans>

Now you can see my source of meta data and how I use them to run this simple data mapper and move towards my goal of lightweight persistence and database independence.

Part III : A Simple and Smart Result Mapper

Now a days we make extensive use of Annotations. Whether it is a good or bad practice to mix configuration meta data with code is debatable, but its better than proprietary XML tags. Since we are so used to mixing meta data in our Java code, why not make use of same tactics in building our data mapper.
SQL statements in all databases supports something called an alias for column names. I will use this to map a SQL result column to a property in my bean. This is better because even if my column name changes but my alias remains same my bean will be populated properly.
I use JODD bean utils. You can download the JODD distribution here.  A problem with JODD is that it is not available in any of the global maven repositories. So you need install the same in your local repository by running the following command 
C:\&gt;mvn install:install-file -Dfile=jodd-3.0.9.jar&nbsp; -DgroupId=jodd -DartifactId=
jodd -Dversion=3.0.9 -Dpackaging=jar 
Use the GUI screens if you are using Archiva repository manager. 
I am on windows and I have kept my jar is located at C:\jodd-3.0.9.jar. It has no other dependencies. 

Correction - As pointed out below in the comments section JODD is now available on Maven.

<dependency>
    <groupId>org.jodd</groupId>
    <artifactId>jodd-wot</artifactId>
    <version>3.1.0</version>
</dependency>



Here is the modified abstract dao support class.
package net.breezeware.spring.dao;


import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import jodd.bean.BeanUtil;


import org.apache.commons.lang.reflect.ConstructorUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.simple.SimpleJdbcDaoSupport;

/**
* @author dhrubo
*
*/
public abstract class AbstractBaseDaoSupport extends SimpleJdbcDaoSupport{
private Logger logger = LoggerFactory.getLogger(AbstractBaseDaoSupport.class);

private Map<String, String> sqlMap;


protected List<?> queryForList(String id, Class primaryType, Object ...params) {
String sql = sqlMap.get(id);
List<Map<String, Object>> mappedResultList = this.getSimpleJdbcTemplate().queryForList(sql, params);

return this.preapreList(mappedResultList, primaryType);
}

protected List<?> queryForList(String id, Class primaryType) {
List<Object> result = new ArrayList<Object>();
String sql = sqlMap.get(id);

List<Map<String, Object>> mappedResultList = this.getSimpleJdbcTemplate().queryForList(sql, new HashMap());
return this.preapreList(mappedResultList, primaryType);
}


protected Object queryForObject(String id, Class type, Object ...params) {
String sql = sqlMap.get(id);
Map<String, ?> dataMap = this.getSimpleJdbcTemplate().queryForMap(
sql, params);

return prepareObject(dataMap,type);
}

protected void insert(String id, Object ...params ) {
String sql = sqlMap.get(id);
this.getSimpleJdbcTemplate().update(sql, params);
}

private List<?> preapreList(List<Map<String, Object>> mappedResultList,Class primaryType) {
List<Object> result = new ArrayList<Object>();
Object holder = null;
for(Map<String, Object> resultMap : mappedResultList) {
holder = prepareObject(resultMap,primaryType);
result.add(holder); 
}

return result;
}
private Object prepareObject(Map<String, ?> resultMap, Class primaryType) {
Iterator<String> it = resultMap.keySet().iterator();
Object holder = getNewObjectInstance(primaryType);

String name = null;
Object value = null;

//set all the properties
while(it.hasNext()) {


name = it.next();
value = resultMap.get(name);

logger.debug("Mapping property = {}, value = {}",name,value);

BeanUtil.setPropertyForcedSilent(holder, name, value);
}

return holder;

}



private Object getNewObjectInstance(Class clazz) {
Object object = null;
try {
object = ConstructorUtils.invokeExactConstructor(clazz, null);
} catch (Exception e) {
throw new RuntimeException(e);
}
return object;
}

/**
* @param sqlMap the sqlMap to set
*/
public void setSqlMap(Map<String, String> sqlMap) {
this.sqlMap = sqlMap;
}


}




This class is by no means complete and is evolving. But it has the essential methods to get the ball rolling. This class uses the Spring JDBC to execute the SQL statements. The SQL statements are picked up from the externalized cache. It utilizes the meta data or column names in the SQL result set retrieved and populated by Spring JDBC as keys in those row maps. Note that in case a column does not have corresponding bean property, it will escape silently. With smart configuration (will show examples soon), this can support nested properties.

Part II : A Simple and Smart Result Mapper

I am a big fan of Spring JDBC. The reasons are simple -
  • Full control over SQL. I can optimize, tweak and tune them to my free will. Let me think in terms of those tables and not objects.
  • Cuts down my DAO code significantly.
  • Takes care of all boilerplate code.
  • Integrates well with other parts of my application which mostly uses other Spring components.
  • Simple and easy to setup and get running at high speed
  • Minimal learning curve
One area where Spring framework does not do a good job is that of list/finder queries returning n number of records. Lets say you want to find the employees in a certain department. The query is executed and you get a map of records, but then you need to return a list of domain objects to the business tier. You will loop through the map list returned by Spring JDBC, for each of your record create a Javabean populate each field and then add to another list which will be finally returned. So there is lot of boilerplate code here.  Look at the example code below, which fetches all users in my system.
public List<User> listUsers() {
String SQL_LIST_USER = "SELECT first_name,last_name,email,user_id FROM t_user";
        List<Map<String,Object>> users = this.getSimpleJdbcTemplate().queryForList(SQL_LIST_USERS,new HashMap());
        List<User> userList = new ArrayList<User>();
        User userHolder = null;
        for(Map<String,Object> user : users) {
            userHolder = new User();
            userHolder.setFirstName((String)user.get("first_name"));
            userHolder.setLastName((String)user.get("last_name"));
            userHolder.setUserCode((String)user.get("email"));
            userHolder.setUserId((Integer)user.get("user_id"));
            userList.add(userHolder);
        }
        return userList;
    }
There is significant redundant code here. If you notice carefully, if a column name changes this code will lead to errors. You may consider this mapping and listing in a row mapper, but still you need to write this code and unnecessarily add new classes per such list method for Spring JDBC callbacks.
So I looked for a data mapper. The best solution in this regard is iBatis. It is much simpler and has less learning curve compared to ORM and tries to do limited things. While playing with it I was once again struck by XML meta data hell. This time mapping each SQL with different maps. This could be some XML to maintain in a decently large project. Also it queries database multiple time if I need to populate object graphs. Also my attempts to integrate iBatis 3 with Maven 2 and Spring 3 failed with ClassNotFoundException. Hence my journey with iBatis ended very abruptly. I was looking for a smarter solution, which I could configure very easily, should be very simple, no learning curve, efficient and intuitive.
The solution was in Spring framework, bit of SQL trick and an external super efficient bean manipulation library called JODD - http://jodd.org/doc/beanutil.html
As a first step towards building this simple and smart data mapper, I want to externalize my SQLs. So I introduce an abstract dao support class which does load externalized SQLs from a Spring configuration file. Note I am not using any additional XML file for this. This will again lead same problems as in iBatis. Instead its better to stick to what I know best. Here is the first version of this abstract class.
Listing – AbstractBaseDaoSupport.java
package net.sf.webplug.spring.dao;  
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;  
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.simple.SimpleJdbcDaoSupport;  
/**
* @author dhrubo
*
*/
public abstract class AbstractBaseDaoSupport extends SimpleJdbcDaoSupport{
    private Logger logger = LoggerFactory.getLogger(AbstractBaseDaoSupport.class);
    private Map<String, String> sqlMap;  
    /**
     * @param sqlMap the sqlMap to set
     */
    public void setSqlMap(Map<String, String> sqlMap) {
        this.sqlMap = sqlMap;
    }
    public String getSql(String id) {

return this.sqlMap.get(id);
    } }
Now I change my Dao class to use this abstract class instead.
Listing – UserDaoImpl.java
package net.sf.dms.security.dao.impl;  
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;  
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.simple.SimpleJdbcDaoSupport;  
import net.sf.dms.security.dao.api.UserDao;
import net.sf.dms.security.domain.User;  
/**
* @author dhrubo
* 
*/
public class UserDaoImpl extends AbstractBaseDaoSupport implements UserDao {  
    private Logger logger = LoggerFactory.getLogger(UserDaoImpl.class);  
    @Override
    public List<User> listUsers() {
        String sql = this.getSql("listUsers");
        List<Map<String,Object>> users = this.getSimpleJdbcTemplate().queryForList(sql,new HashMap());
        List<User> userList = new ArrayList<User>();
        User userHolder = null;
        for(Map<String,Object> user : users) {
            userHolder = new User();
            userHolder.setFirstName((String)user.get("first_name"));
            userHolder.setLastName((String)user.get("last_name"));
            userHolder.setUserCode((String)user.get("email"));
            userHolder.setUserId((Integer)user.get("user_id"));
            userList.add(userHolder);
        }
        return userList;
    }  
} 
The sql is now moved to an Spring config file (separate just for SQLs)
Listing – sql-repository.xml
<?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-3.0.xsd">  
    <bean id="secSqlMap" class="org.springframework.beans.factory.config.MapFactoryBean">
        <property name="sourceMap">
            <map>
                <entry key="listUsers">
                    <value>
                        <![CDATA[
                            SELECT first_name ,last_name ,email ,user_id  FROM t_user
                        ]]>
                    </value>
                </entry>
                
            </map>
        </property>
    </bean>  
</beans> 
Now that I have externalized the SQLs, its time to look into the main configuration file. There is something interesting here too.
Listing – applicationContext.xml
<?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-3.0.xsd">
    <import resource="sql-repository.xml"/>
       <bean id="secDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="org.postgresql.Driver"/>
        <property name="url" value="jdbc:postgresql://localhost:5432/dms"/>
        <property name="username" value="postgres"/>
        <property name="password" value="postgres"/>
    </bean>
    <bean id="abstractSecBaseDaoSupport" class="net.sf.spring.dao.AbstractBaseDaoSupport" abstract="true">
            <property name="dataSource" ref="secDataSource"/>
            <property name="sqlMap" ref="secSqlMap"/>
    </bean>
    <bean id="userDao" class="net.sf.dms.security.dao.impl.UserDaoImpl" parent="abstractSecBaseDaoSupport" />
    <bean id="roleDao" class="net.sf.dms.security.dao.impl.RoleDaoImpl" parent="abstractSecBaseDaoSupport"/>
    <bean id="userRoleDao" class="net.sf.dms.security.dao.impl.UserRoleDaoImpl" parent="abstractSecBaseDaoSupport"/>
</beans> 
Note the abstract class configuration. I do not need to configure the data source property for each dao class anymore. This ends my first step of clean up. In the next post I will show how to extend the abstract class to provide mapper functions.

Part I : A Simple and Smart SQL Result Mapper

I am not at all a fan of ORM solutions/frameworks like Hibernate. I have already written and presented my view on different forums and discussions the reasons for my disliking. I truly empathize with Ted Neward that ORM are “Vietnam of Computer Science”.
http://www.codinghorror.com/blog/2006/06/object-relational-mapping-is-the-vietnam-of-computer-science.html
http://blogs.tedneward.com/2006/06/26/The+Vietnam+Of+Computer+Science.aspx
Followup - http://blogs.tedneward.com/2006/06/27/Thoughts+On+Vietnam+Commentary.aspx
http://stackoverflow.com/questions/404083/is-orm-still-the-vietnam-of-computer-science
Some counter punches
http://www.codeproject.com/KB/architecture/ORM_Vietnam.aspx?display=Print

  • I am not convinced as to why should I learn HQL or similar QLs provided by other OR Mapping solutions? Why should I not write and benefit from SQLs which have been proven to be so powerful over the ages and often outlive the lifetime of an application. So many times I have seen SQLs and Stored procedures being reused as applications moved from say .NET to Java and vice-versa.
  • There is significant learning curve to an ORM add to those fancy concepts like lazy loading(if you need lazy loading you must first think that there is some problem, why are you afraid of object creation with modern day JVM and hardware or is it that you fear you will create too many objects?).
  • Why do I generate, tweak so many XMLs worry about so much XML based syntaxes, how do I efficiently manage these XMLs and alter later if required? There are too many XML elements and attributes some hidden undocumented? Oh this is real pain. Annotations solve some of the meta data hell, but I am still in a dilemma if mixing meta data with code is a good practice?
  • Why do think of my joins in terms of objects when they are best done with relational tables? Sorry I can only think of joining tables and not my objects.Live and let them live in their own world.
  • There is no doubt ORMs are powerful and tries to make life easy. But the learning curve and deadline pressures often forces developers with somehow acquired knowledge by reading few articles and getting started guides from here and there to code and then finally when issues crop up especially too many objects, JVM crashes and sever performance worries the application falls apart and you focus more on solving these than business logic.
  • Even dangerous trend that I see these days is the advent of ORM specific profilers. What does this imply? Yes the ORMs are serious cause for performance bottlenecks in your applications. I know someone came to me few months back, asking why his JVM crashes when he is running his search queries and paging? His table just had about 150k records and JVM heap was 2GB. Not a bad setting at all? Is it because the ORM was fetching a significant subset of the records based on the search criteria,first to application server before starting pagination? or my friend had a bad QL statement?
  • I know ORMs can help with optimistic lock? But do they help with phantom records problem?
  • Why should I cache on application server and allow or create a slightest possibility of my JVM to burst? Does caching on JVM really increase the application performance? I always knew and still continue to believe the best place to cache database records is in the database memory. Can we not gain on performance by keeping these data to where it belongs, which have been long tuned and proven to optimize performance, reducing network trips, setting tips to bulk fetch data when required, fetch data in optimal blocks? You may be tempted to use caching systems which hides behind the ORM. But think in case of an issue you have the pain of learning another framework and then fixing your errors, if Googling does not help.
  • How does your ORM populate the object graph? Does it fire query after query going down the graph? If yes think about the domain model? Or think about your ORM implementation? Is there any way out? My answer is yes, smart SQL + smart mapping. I will try to show this with an example.
  • However, ORMs are good, if you have indepth knowledge of the framework under consideration. Then with an ORM you can significantly cut down code in your DAO layer. This is also a myth. With Spring JDBC you can reduce your code even more or equal to what you can with an ORM. You can read an article I wrote long back on OTN(actually wrote in erstwhile BEA DEV2DEV) here to start thinking about this - http://www.oracle.com/technology/pub/articles/dev2arch/2006/10/spring-jdbc-dao.html
  • One area I thought I might use ORM is when I design a product which needs to support multiple databases. But then I realised this is not true, if we manage to externalize our SQL and have an efficient strategy to map SQL result set to our domain object we can achieve database independence. 99% of the applications are not meant to be db independent. If your customer has investment so much money to procure license, build competency buy hardware for that big blackbox for Java developers called RDBMS why would he want that box of money, time and effort go down the drain by replacing it with another. So if you are trying to sell me an ORM for db independence I will not simply not buy in.
  • ORMs dependent on several 3rd party libraries. Do I need to increase 3rd party dependencies? Yes you will need 3rd party jars but we must make effort to keep them to minimal. There may be version collisions between 3rd party libraries used by your ORM and main framework.

Thursday, May 20, 2010

A custom plug-in system for web applications

Recently I was trying to put together a plugin system for web applications. The idea is similar to Eclipse plugins. Where you bundle your extension in a jar and then drop them in Eclipse-Home/plugins folder, restart Eclipse and you are ready to use it. Note that Eclipse plugins are OSGi plugins.

So my initial effort was to see if I could build a pluggable web application with OSGi. After few experiments with Equinox (the Eclipse OSGi engine) and Felix, I moved on to check out Spring DM as well as Spring DM server. But all I all I felt that

  • OSGi / DM involves significant learning curve.
  • The web server bundles are “probably” not of enterprise strength.
  • Still trying to gel with JEE.
  • Significant extra effort required to port applications to OSGi platform.

All in all  OSGi / DM has to go few more miles before we build Enterprise server apps using those containers / bundles. But its a very good start and promises a lot in the future.

So what to do? I started digging dip into Spring framework for a while and soon came up with an idea of a simple plug-in system for web applications. This plug-in system should allow you to package your application components(controllers,business objects, data acccess)  in a jar file with mandatory Spring config file. This jar file should be dropped in WEB-INF/lib and should be ready for use once the web container is restarted or this application is restarted. It should also allow you to package your view components as well in the jar.

In the next few posts I will try to show how such a simple yet effective system can be build by extending the Spring framework. I will also show some good practices that I learnt while building applications with this framework extension which I call WebPlug. The code and documentation will be available soon on Sourceforge.