Friday, July 17, 2009

MVC in the world of AJAX and SOA

Recently I was hit with the question - How does MVC play in AJAX world? Well, below is the perspective I put forward although not so eloquently or in such detail. My response expanded the scope from MVC and AJAX to include the more widely adopted back end architecture - SOA (Service Oriented Architecture). I am not sure if I was able to put across my thoughts vividly to the other person but based on the impression I got, I guess not. So I thought I blog about it to reach out to the online community and validate my thoughts.

Abstract:
The traditional MVC pattern requires a fundamental change in terms of the roles played by the three layers. This need arises from the advent of SOA at the server end and AJAX at the client end.
Please note that this is not about how the communication i.e sync or async occurs between the various layers. This is at a higher level and hence the sequence diagrams captured below may not depict the exact communication patterns.

Detail:
Traditional MVC has been:
Model: The data access layer and data persistence. This is the Hibernate, JPA layer in case of Java.
View: Presentation layer i.e how data is presented to user. JSP, JavaScript, HTML fall into this category.
Controller: Data validation, transformation and control the flow i.e identify the next view to be rendered. In case of Java, Servlets are used as controllers.





But in today's world where data driven architectures are replaced with service oriented architectures, the needs have changed with a diverse set of clients seeking the same set of information. The model is wrapped in a service layer that provides all the functionality required for diverse set of clients that include:
- A SOAP / WebService (i.e WS-*) client.
- API client i.e users need a programmatic access to the underlying functionality, either to enhance the functionality or integrate it into their own services.
- GUI - thin i.e web based, as well as thick i.e from IDE's such as Eclipse etc..

So in order to address the above needs, how can MVC help. Obviously the traditional MVC has to undergo few changes.
Model: is now wrapped by the service layer with enhanced set of functionality that enables distributed cache, scalability etc., across diverse set of client.

Controller: Since the data validation and transformation are needed by all the clients, these need to be moved into Service layer. So Controller is now left with flow logic only i.e to identify the view for the corresponding user event.

View: Any business logic at this layer needs to be moved into the service layer since the application MUST exhibit a consistent behavior across the diverse set of clients. How this data is rendered to the user is what primarily exists in the view and is the prerogative of the client.

Before we dive into how the layers can be refactored, let us how AJAX influences the layers. In the world of AJAX, the web UI is designed in a more modular fashion and there is a lesser need to render the complete page for every event. Only a certain content on the page could be refreshed with a different data set. The view remains the same. For eg: when browsing contacts page, the set of fields displayed for each user - First Name, LastName, Address etc., are the same. What changes when a different user is selected is the value of the First Name, Last Name and other fields. In other words the view stays the same while the data set is what changes. So the only role the controller plays is delegation from view to service / model. In other words, the role of Controller has diminished to that of a delegator.

The question arises to which layer does the Controller now really belong to? Should it be part of the View since its only role is to identify the view? Probably yes. The result is, if the view needs to change, either for a complete re-write to upgrade to latest technologies or for refactor purposes, changes at the View layer will in all probability effect the controller layer or what ever we may call it. But it is not necessary that the service layer undergo's any change.




The above is something we were able to achieve using GWT. I am not sure how the wide range of MVC frameworks out there enable the above. But, based on my past experiences, in an effort to enforce MVC pattern these API and interfaces could be rigid, although I would request the experts on these frameworks provide their inputs.

Wednesday, July 8, 2009

Operating System - What I expect as a user

With Google announcing, late yesterday evening, a new Operating System Google Chrome OS (http://googleblog.blogspot.com/2009/07/introducing-google-chrome-os.html), my first reaction was - What? Another OS that does the same myriad of things or does it take the OS to total different level, that I as a user have always wanted?

This new OS is in addition to the already available Android OS from Google that was announced as part of its strategy for smart phones, set-top boxes and other embedded devices. Google claims the need for this OS is to address the needs of primary web users who need the basic functionality of Speed, Simplicity and Security. I would not be surprised if Google takes this to the next level where in the OS meets the needs of the advanced users - the desktop users. I have longed for innovation in OS's which have changed little over the past two decades. Some of the features I have longed in OS are:
- Negligible boot up latency: As a user I care little on what the OS is doing and expect that I be able to operate on my system as soon as I switch it on without having to wait for it to boot up its internals.

- Apply changes immediately: In case of Windows as well as Mac, there are programs that require restart of the system which is annoying especially if I am in the midst of some work and happen to install the updates for these programs.

- Versioning: Ability to store the changes to a file as user modifies it. Although Vista does provide a versioning system, the hard drive can fill up pretty quickly. I do not know the internals on how Vista stores these versions but I am sure storing just the diffs between the prevoius file should not exhause the hard drive easily. Assuming Vista stores only the diffs, then there is a huge opportunity here to device new means by which the diffs can be stored between two instances of the same files.

- Disk Usage Visualizer: This can be an immense utility that provides a 2D or 3D view of the space occupied by each file or application on the hard drive. For eg: Mac has an utility provided by third party developers - GrandPerspective (http://grandperspectiv.sourceforge.net/#download) that provides a 2D view of the disk usage. This enables optimization of the disk space by identifying unwanted applications and files and quickly getting rid of them. Typical use case is when multiple Virtual machines are installed hosting different OS. This utility helps identify the space occupied by the VM instance and optimizing or cleaning up some of the space.

- Ability to define the life cycle of an application or file: The ability to say when a file should be trashed, or when an application must be un-installed etc.. As a user who researches bunch of software, I tend to forget to uninstall trial downloads. It would be nice if the OS provided a way to notify user stating "this software license has expired, do you want to uninstall?".

- A better File exploration experience: Some of the most simple use cases are not handled by today's OS. The ability to flatten out all directories to view all the files in the parent directory. At times, I have wanted to view all the src files in the "src" directory. Unfortunately, either I traverse through each dir or use an Unix console to view all the files.

- Ease of personalization of the OS: One feature I would love to have is the ability to right click and add my own custom operation. This is possible today and is used by wide variety of tool providers in integrating their tool into right click option. But this requires understanding of the OS architecture and its API's. If these API's were agnostic of a specific programming language or uniform across multiple OS it would be worth while spending the time researching on it. Else to research each OS is a huge waste of time. One use case for this has been to add the ability to right click and encrypt or decrypt a file or directory.

- Backup & Recovery: Supposedly, Sun's ZFS does a great job in recovering all the files and ensuring no data loss or corruption. I would love to have these features in main street OS offerings such as Windows or Mac. There is enough important work that I do on a daily basis that I would hate to loose due to system crash or hardware failure. Once they crash, retrieval of data is not easy nor is it cheap. I had to shell out ~$1200 to retrieve the data on my hard drive that crashed on me. Incidentally the price of the laptop itself was around ~$1200.

- Sorting of Directories in File explorer tree: I would love to have a file explorer that sorts the directories based on the most used directories. By default, Windows tree on the left side sorts the directories based on name. But, given the personalized way that I work with my file systems there are couple of directories that I access more often when compared to most others. Hence I would love to have my top priority directories displayed at the top in the tree. This will avoid having to scroll down at times to select this directory.

The above are a few that are on top of my mind and as and when I recollect other features I would like to see in OS, I will add to the above list.

Wednesday, February 11, 2009

Getting started with Amazon WebServices (S3)

Amidst the slew of cloud computing offerings, one company that has stood out in their approach and marketing to attract independent developers is Amazon. A B2C company whose primary business is to sell goods online, has entered a totally different space - cloud space. Although, to my knowledge Sun Microsystems Inc.,was way ahead in this space, I believe, the company failed to put together a strong marketing message and easy-to-use API's to reach out to the development community and the budding Entrepreneurs.

Amongst the many who were attracted towards Amazon, I was one of them. Although I signed up quite some time back, it took me some time before I could execute the first program. Below is what I did to get a basic understanding of the services, the first of which I chose was S3 - the storage service.

Pre-requisites:
- Java 1.5 and above. I used JDK 1.6
- Preferably an Editor. I used Eclipse. Makes life so easy.
- Create an Amazon WebServices account at aws.amazon.com. You need the Access ID and Secret Key.
- A decent amount of understanding of Java.

Steps:
  • Download sample code from http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1366&categoryID=47.
  • Extract the ZIP to a directory.
  • Start Eclipse. Create a New Java Project and in the window, point the src to the above extracted directory where contents of the ZIP file are extracted. Note: Although the ZIP contains java, ruby and python files only java files would be visible in the project.
  • Open the file ExampleUsage.java which contains the main method to execute the code. In the main method, to take baby steps, I commented out all the method calls except usage.s3ServiceOperations().
  • In the same class, edit the method s3ServiceOperations(), replace the constructor with 2 args by constructor with 4 args that intakes AccessID and SecretID. Hard code the ID values and run the class as a simple Java Application. REST is the transport used for executing the code which you can refer to the code in class AWS which is the super class to class S3.
The REST style request that goes out to AWS is as below.
Method : GET
URI : https://s3.amazonaws.com
Headers:
Host=s3.amazonaws.com
Date=Fri, 13 Feb 2009 00:42:53 GMT
Content-Type=
Query Parameters:
Authorization=AWS 149VSd09S1C9Wt8Rm6R2:pkuInE4ZvFfw9wKdtQiZ1u1JbqA=
Host=s3.amazonaws.com
Date=Fri, 13 Feb 2009 00:42:53 GMT


The output, upon executing the above, would be as shown below - first part is the HTTP header followed by the Body. In case you see an exception stating 'NotSignedUp' with HTTP 403 error, you will need to sign up for the S3 service at http://aws.amazon.com/s3/.

Status : 200 OK
Headers:
null=HTTP/1.1 200 OK
x-amz-request-id=752C44D5CBA6171E
Date=Fri, 13 Feb 2009 00:42:49 GMT
Transfer-Encoding=chunked
x-amz-id-2=hp1PQw1VZSOh2swSE/00SJomoDpyfrMuB01g353Le8GbcZTMrDmg6FuvYMWjP53S
Content-Type=application/xml
Server=AmazonS3

Body:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<ListAllMyBucketsResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<Owner>
<ID>b77136276767d460dc6ea34ff6cc338489d1a4c8d7db343b7f08054170f1fea4</ID>
<DisplayName>vyaapti</DisplayName>
</Owner>
<Buckets/>
</ListAllMyBucketsResult>

Note, in the above <Buckets/> element is empty.

Creating a bucket:
In the simplest terminology, buckets is the term AWS uses to group a set of objects with a unique namespace. For more details, please refer to AWS documentation.
To create a bucket, in the above mentioned method s3ServiceOperations(), uncomment the below line that creates the bucket within the System.out statement. In my case, I also moved the System.out statement that prints the list of buckets below the above statement to reduce the number of invokes and hence save some pennies.:-) (Remember ever invoke is a data transmition to AWS and you will be charged for the same depending on the data).
After the above changes, execute the class and you should see the request going out as:

Method : PUT
URI : https://test.location3.s3.amazonaws.com/
Headers:
Expect=100-continue
Host=test.location3.s3.amazonaws.com
Date=Fri, 13 Feb 2009 01:19:28 GMT
Content-Length=146
Content-Type=application/xml
Request Body Data:
Body:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<CreateBucketConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<LocationConstraint>EU</LocationConstraint>
</CreateBucketConfiguration>

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<CreateBucketConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<LocationConstraint>EU</LocationConstraint>
</CreateBucketConfiguration>

While the output is as below:

Status : 200 OK
Headers:
null=HTTP/1.1 200 OK
x-amz-request-id=218387ACA024E346
Date=Fri, 13 Feb 2009 01:19:23 GMT
Content-Length=0
x-amz-id-2=BuzexE972zyJii/kPzUn0qhfUqPXDNmL2Myic0blVgr7b4Qc3s0vENGLklSuUzlS
Location=http://test.location3.s3.amazonaws.com/
Server=AmazonS3


While the list of buckets, as executed previous would be:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<ListAllMyBucketsResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<Owner>
<ID>b77136276767d460dc6ea34ff6cc338489d1a4c8d7db343b7f08054170f1fea4</ID>
<DisplayName>vyaapti</DisplayName>
</Owner>
<Buckets>
<Bucket>
<Name>test.location3</Name>
<CreationDate>2009-02-13T01:19:24.000Z</CreationDate>
</Bucket>
</Buckets>
</ListAllMyBucketsResult>

There is so much more to the above, adding ACL (Access Control Lists), creating objects etc.. I wish I get the time to research more on this soon, so that I can continue to this post. But for now I will use the available time to read the developer guide at http://docs.amazonwebservices.com/AmazonS3/2006-03-01/.

Friday, January 16, 2009

Getting started with Spring Framework - II

This is the second part in my effort at getting to know Spring Framework. Please refer to the first part on the same blog on 15 Jan 2009.

5. Security Aspect.
In continuing with the previous Logging Aspect, this adds a Security Aspect with a simple introduction to Acegi Security and how it can be used to store user information. For more details on Acegi Security, please refer to [9].

First we will reuse the DBDataReaderUsingPropertyHolder class we created in exercise (3). Create the SecurityAspect class with an 'init' method that is executed before any method in class 'DBDataReaderUsingPropertyHolder' is executed i.e with AOP advice='before'. This init method adds a user to Acegi SecurityContext. We then add another method to validate this user, 'checkSecurity()'. This method, which is executed when the method is executed i.e with AOP Advice='around', retrieves ths user ID and prints it out.
package org.spring.learn.class1;

import org.acegisecurity.Authentication;
import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.GrantedAuthorityImpl;
import org.acegisecurity.context.SecurityContext;
import org.acegisecurity.context.SecurityContextHolder;
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import org.acegisecurity.userdetails.User;
import org.acegisecurity.userdetails.UserDetails;
import org.aspectj.lang.ProceedingJoinPoint;

//@Aspect
public class SecurityAspect {

/** this method initializes the Acegi Security Context with a Principal.
*/
public void init() {
System.out.println("Security Aspect: In init method");
SecurityContext secCtx = SecurityContextHolder.getContext();

GrantedAuthority[] gas = new GrantedAuthorityImpl[] {new GrantedAuthorityImpl("ADMIN")};
UserDetails userDetails =
new User("samba", "stc", true, true, true, true, gas);

// InMemoryDaoImpl userDetailSvc = new InMemoryDaoImpl();
// UserMap um = new UserMap();
// um.addUser(userDetails);
// userDetailSvc.setUserMap(um);

UsernamePasswordAuthenticationToken unpat =
new UsernamePasswordAuthenticationToken(userDetails, userDetails);
secCtx.setAuthentication(unpat);
}

// just defining here did not work. Investigate later. @Around("org.spring.learn.class1.DBDataReaderUsingPropertyHolder.readData()")
/** this method checks if Principal exists in the Acegi Security Context
* and prints the user name. This method MUST be executed with 'Advice=around'
* since it intakes the ProceedingJoinPoint param.
*/
public Object checkSecurity(ProceedingJoinPoint call) throws Throwable {

SecurityContext secCtx = SecurityContextHolder.getContext();
Authentication auth = secCtx.getAuthentication();

if (auth != null) {
Object obj = auth.getPrincipal();

String userName = null;
if (obj instanceof UserDetails) {
userName = ((UserDetails) obj).getUsername();
} else {
userName = obj.toString();
}

System.out.println("Authenticated the user....= " + userName);
} else {
System.out.println("Authentication object not initialized.");
}

return call.proceed();
}

}

The Application Context XML file to execute the above would be:
<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

<context:property-placeholder location="resource/config/**/db.properties"/>

<!-- db access -->
<bean id="dbDataReaderUsingPropertyHolder" class="org.spring.learn.class1.DBDataReaderUsingPropertyHolder">
<property name="dataSource" ref="datasource"/>
</bean>

<bean id="datasource"
class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${user}"/>
<property name="password" value="${password}"/>
</bean>

<!-- Security Aspect -->
<bean id="securityAspectBean" class="org.spring.learn.class1.SecurityAspect"/>

<aop:config>
<aop:aspect id="securityAspect" ref="securityAspectBean">
<aop:before method="init" pointcut="within(org.spring.learn.class1.DB*)"/>
<aop:around method="checkSecurity" pointcut="within(org.spring.learn.class1.DB*)"/>
</aop:aspect>
</aop:config>
</beans>

Now execute the main method in DBDataReaderUsingPropertyHolder to view the result.

6. Bean scope:
Spring provides 5 different scopes that a bean can be defined under - singleton, prototype, request, session, global session. The last 3 are specific to web aware ApplicationContext's.

Singleton: One instance only is created per container for that particular bean definition in the ApplicationContext file. The difference with Spring's singleton when compared to GoF singleton pattern is - Spring's scope is per container per bean while GoF's is per classloader. Default scope for bean's defined in Spring. A Session less bean.

Prototype: Multiple instances are created for the same bean definition everytime a request is made through ApplicationContext for the object. A stateful bean. To use Prototype, scope must be explicitly defined for the bean. One major difference in life cycle management here is, Spring does not invoke the destroy callback for a Prototype bean. Once the bean is initialized and handed to the client, Spring has no knowledge of the Prototype bean. There is a custom way of enabling this. For details refer to [10].

Please note that this is just an intro and there are more details such as the behavior of a Singleton bean injected with a Prototype Bean, the HTTP session scoped bean handling etc.. For all the details on scope's please refer to [11].
The simple test class is as below. In the main method, for the Singleton we invoke the getBean(..) multiple times and check if the hash values of the objects are identical and the result is true since the same object is returned. You can also observe that the println statement in the constructor is execute the first time only. For the Prototype, we invoke the getBean(..) multiple times and compare the returned object hash values. The result is false since every time we invoke getBean(..) a new object is returned. Here you can observe that the println statement in the constructor is executed everytime the get method is invoked.

package org.spring.learn.class1;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

/** This test provides an overview of inherently supported scopes for beans in
* Spring - primarily Singleton and Prototype. It also depicts the added flexibility
* Spring provides in the ability to define a bean class under two different scope's.
*/
public class BeanScopeTest {

public BeanScopeTest() {
System.out.println("Bean Scope test....");
}

public static void main(String args[]) {
ApplicationContext appCtx = new FileSystemXmlApplicationContext("resource/appCtx-BeanScope.xml");
/*--- Singleton ---*/
//the log in constructor should be printed
BeanScopeTest singleton = (BeanScopeTest) appCtx.getBean("singletonBeanScope");
//log in constructor should not be printed.
BeanScopeTest singleton1 = (BeanScopeTest) appCtx.getBean("singletonBeanScope");
//output = true
System.out.println("Are the two singleton beans's equal? = " + (singleton == singleton1));

/*--- Prototype ---*/
//the log in constructor should be printed
BeanScopeTest prototype = (BeanScopeTest) appCtx.getBean("prototypeBeanScope");
//the log in constructor should be printed
BeanScopeTest prototype1 = (BeanScopeTest) appCtx.getBean("prototypeBeanScope");
//output = false
System.out.println("Are the two Prototype Beans equal? = " + (prototype == prototype1));

//3 other bean scopes supported by Spring are specific to Web-Aware ApplicationContext.
}
}

The Application Context XML file defines two different bean ID's for the same bean class. One bean ID has default scope which is Singleton while the other has Prototype.
<?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-2.0.xsd">

<bean id="singletonBeanScope" class="org.spring.learn.class1.BeanScopeTest"/>

<bean id="prototypeBeanScope" class="org.spring.learn.class1.BeanScopeTest" scope="prototype"/>

</beans>


Ref:
[9] http://www.acegisecurity.org/guide/springsecurity.html
[10] http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-factory-extension-bpp
[11] http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-factory-scopes

Thursday, January 15, 2009

Getting started with Spring

Across various technical discussions, articles, forums and even in job postings, there is always a mention about Spring framework. Given this hype around it, I decided to get acquainted with the framework to understand its pros and cons. In this process I documented the individual steps I took in understanding the concepts of the framework as detailed below. These are only a few I have got to so far and as and when I get time I will update the same with additional features. I have avoided details about specific class objects and would recommend you to refer to articles in the References section.

Although Spring installable (ZIP file) does come with samples, I decided to not get started with the samples since they are tied to the web framework. But I did refer to the samples for some of the tasks such as connecting to the DB and would recommend the same for everyone once you understand the basic concepts.

Requirements to get started:
  • A good understanding of Java.
  • An understanding of IoC [1] and Dependency Injection [2]. Refer to the corresponding references for a good description on these patterns.
  • Access to Spring API documentation and other tutorials that provide basic idea about some of the concepts used here in.
  • An assumption that you use an IDE since no execution scripts such as batch files etc. are provided. Knowledge in configuring the classpath in the IDE also is required. For eg: In Eclipse you can configure the classpath in the 'Java Build Path' section in Properties window for the specific project. Right click on the project and open the properties.
To execute all the examples you will require 'spring.jar' primarily and depending on what you are executing, corresponding jars will need to added to the classpath.

  1. Hello World: This example is the simplest case that shows how method injection can be done using Spring. The application of this feature can vary depending on the system being built. But some of the common applications could be setting default properties on beans, for creating DataSource. Some of these will be demonstrated as we slowly step into Spring features.

    Start with the simple use case Hello World. Start by creating a simple class HelloSpringBean with a property - 'message'. Handcode or generate the setters and getters using your IDE. To test Spring's functionality, write a main method that creates the ApplicationContext object, get an instance of HelloSpringBean and invoke the getter method without having to invoke the setter method.

    The ApplicationContext object is a Spring interface that is instantiated by providing an implementation of this interface with the location of the bean resource file. In our case since the bean resource is an XML on the file system we use the FileSystemXmlApplicationContext class. This class acts like a service or bean locator for those defined in the XML file. For further details please refer to [8].

    package org.spring.learn.class1;

    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.FileSystemXmlApplicationContext;

    public class HelloSpringBean {

    private String message;

    public void setMessage(String msg) {
    this.message = msg;
    }

    public String getMessage() {
    return this.message;
    }

    public static void main(String[] args) {
    ApplicationContext ctx = new FileSystemXmlApplicationContext("resource/applicationContext.xml");
    System.out.println("Completed loading of the ApplicationContext");

    //simple bean with setter injection
    HelloSpringBean bean = (HelloSpringBean) ctx.getBean("helloSpringBean");
    //invoke the get method.... and check the output. Note. the set method has not been invoked.
    System.out.println(bean.getMessage());
    }
    }

    The required applicationContext.xml file to execute the above is shown below. Please ensure this file is dropped in the directory 'resource' which is a peer to the 'src' directory.

    <?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-2.0.xsd">

    <!-- simple setter injection -->
    <bean id="helloSpringBean" class="org.spring.learn.class1.HelloSpringBean">
    <property name="message" value="Hello, Spring"/>
    </bean>
    </beans>

    With regarding to when the bean is created, the interesting observation is that the bean is created when the ApplicationContext object is created and not when ctx.getBean(..) method is invoked. To enable lazy loading, you can use the attribute 'lazy-init' as shown for the below bean definition.
    <bean id="helloSpringBean" class="org.spring.learn.class1.HelloSpringBean" lazy-init="true">
    <property name="message" value="Hello, Spring"/>
    </bean>
    Execute the main method in the above HelloSpringBean class to see the result.


  2. Accessing a Database: To execute this example you require
    Apache's commons-dbcp.jar to be in the classpath along with other jar files required for executing the example (1).

    To access a database in Spring, we will configure a DataSource in the applicationContext.xml file and access the Databaseto retrieve all the columns in a table.

    The below class DatabaseDataReader is instantiated by Spring framework and the DataSource object injected into the constructor. Note the difference here is constructor injection when compared to previous example of setter injection. In the readData() method, Spring's JdbcTemplate class is used since it abstracts out the boiler plate code such as creating DB statements, result sets and their corresponding destruction.
    We then execute the queryForList which intakes a SQL query with no arguments. The reason to use the queryForList method signature as used below is, a PreparedStatement will be created by underlying JdbcTemplate instead of the normal Statement. Please ensure the SQL query matches your DB table definitions. The output of this is a List of Map objects. For further details please refer to javadoc API.

    package org.spring.learn.class1;

    import java.util.Collection;
    import java.util.List;
    import java.util.Map;

    import javax.sql.DataSource;

    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.FileSystemXmlApplicationContext;
    import org.springframework.jdbc.core.JdbcTemplate;

    public class DatabaseDataReader {

    private DataSource datasource;

    public DatabaseDataReader(DataSource ds) {
    this.datasource = ds;
    System.out.println("Datasource set= " + this.datasource);
    }

    public boolean readData() {
    JdbcTemplate template = new JdbcTemplate(datasource);
    List mapList = template.queryForList("select * from EMP", (Object[]) null);

    for (Map m : mapList) {
    Collection val = m.values();
    System.out.println("Value= " + val);
    }

    return true;
    }

    public static void main(String args[]) {
    ApplicationContext ctx = new FileSystemXmlApplicationContext("resource/applicationContext.xml");

    DatabaseDataReader dbReader = (DatabaseDataReader) ctx.getBean("databaseDataReader");
    dbReader.readData();
    }
    }

    To execute the above, you require applicationContext.xml file as shown below. Please ensure this file is dropped in the directory 'resource' which is a peer to the 'src' directory.


    <?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-2.0.xsd">

    <bean id="datasource"
    class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close">
    <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
    <property name="url" value="jdbc:oracle:thin:@localhost:1521:orcl"/>
    <property name="username" value="spring"/>
    <property name="password" value="spring"/>
    </bean>

    <!-- To directly use Oracle's classes.
    <bean id="datasource" class="oracle.jdbc.pool.OracleConnectionCacheImpl" >
    <property name="connectionPoolDataSource">
    <bean class="oracle.jdbc.pool.OracleConnectionPoolDataSource">
    <property name="URL" value="jdbc:oracle:thin:@localhost:1521:ORCL"/>
    <property name="user" value="spring"/>
    <property name="password" value="spring"/>
    </bean>
    </property>
    <property name="maxLimit" value="10"/>
    <property name="minLimit" value="2"/>
    </bean>
    -->
    </beans>

    Now execute the main method in DBDataReader to view the result.
    Instead of Apache's common DBCP API, you could also use DriverManagerDataSource. But the drawback is the connections are not pooled. For pooled connections use Apache's DBCP. [3].


  3. Using Properties instead of hardcoded DB config: To avoid hardcoding values in the context XML file, you can use external Properties to be injected dynamically into the Properties.
    One way to define the location of a properties file is to use
    <context:property-placeholder location="classpath:jdbc.properties"/>
    This is particulary useful when the bean class that requires properties does not inherently support a mechanism to provide Properties. This class is identical to the exercise 2, except that setter injection is used. The primary difference in this exercise is the usage of placeholder property in the context XML.

    package org.spring.learn.class1;

    import java.util.Collection;
    import java.util.List;
    import java.util.Map;

    import javax.sql.DataSource;

    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.FileSystemXmlApplicationContext;
    import org.springframework.jdbc.core.JdbcTemplate;

    /**1. Use PropertyPlaceHolderConfigurer to insert DB properties dynamically from
    * an external properties file instead of hardcoding the values into context XML
    * file.
    * 2. Use setter injection instead of constructor injection in IoC container.
    *
    */
    public class DBDataReaderUsingPropertyHolder {

    private DataSource datasource;

    public DBDataReaderUsingPropertyHolder() {
    }


    /** This method is invoked when this class is instantiated which can be either
    * when ApplicationContext is created or by lazy loading i.e when getBean
    * method is invoked.
    * @param ds
    */
    public void setDataSource(DataSource ds) {
    this.datasource = ds;
    System.out.println("Datasource set= " + this.datasource);
    }

    public boolean readData() {
    JdbcTemplate template = new JdbcTemplate(datasource);
    List mapList = template.queryForList("select * from EMP", (Object[]) null);

    for (Map m : mapList) {
    Collection val = m.values();
    System.out.println("Value= " + val);
    }

    return true;
    }

    public static void main(String args[]) {
    ApplicationContext ctx = new FileSystemXmlApplicationContext("resource/appCtx-PropertyHolder.xml");
    System.out.println("Initialized ApplicationContext");

    DBDataReaderUsingPropertyHolder dbReader =
    (DBDataReaderUsingPropertyHolder) ctx.getBean("dbDataReaderUsingPropertyHolder");
    dbReader.readData();
    }
    }

    To execute the above, the context XML needs to declare a place holder for DB properties as shown below. The property-placeholder element is part of a new schema which is also defined 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:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">

    <!-- a property holder for all the objects within this application context definition. Spring framework will automatically replace the below defined variables -->
    <context:property-placeholder location="resource/config/**/db.properties"/>

    <!-- db access -->
    <bean id="dbDataReaderUsingPropertyHolder" class="org.spring.learn.class1.DBDataReaderUsingPropertyHolder">
    <property name="dataSource" ref="datasource"/>
    </bean>

    <bean id="datasource"
    class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close">
    <property name="driverClassName" value="${driver}"/>
    <property name="url" value="${url}"/>
    <property name="username" value="${user}"/>
    <property name="password" value="${password}"/>
    </bean>
    </beans>

    Using the above variables and property-placeholder, Spring provides one way to separate out dynamic configuration i.e config that is susecptible to user changes such as the need to deploy the same application in different systems environments or user changes for application such as switching an application from test to production by using a switch.

    You can also configure a JNDI resource within the application context file. Below is an example using Oracle.
    <Resource name="jdbc/rac" auth="Container"
    type="oracle.jdbc.pool.OracleDataSource"
    description="Oracle Datasource"
    factory="oracle.jdbc.pool.OracleDataSourceFactory"
    url="jdbc:oracle:thin:@(description=(address_list=(address=(host=rac1)(protocol=tcp)(port=1521))(address=(host=rac2)(protocol=tcp)(port=1521))(load_balance=no))(connect_data=(service_name=racdb1)))"
    user="pet"
    password="clinic"
    ONSConfiguration="nodes=rac1:6200,rac2:6200" //if RAC is required
    fastConnectionFailoverEnabled="true" //if FCF is required.
    connectionCachingEnabled="true"
    connectionCacheName="PETCLINIC"/>


    ---- sample db.properties file ----------
    driver=oracle.jdbc.driver.OracleDriver
    url=jdbc:oracle:thin:@localhost:1521:orcl
    user=orcl
    password=orcl


  4. AOP in Spring: Aspect oriented programming in Spring provides a powerful way to intercept a call to a method - before, after, around, the method's execution which in AOP terms is called 'Advice'. There are other 'Advice''s too, but I will not get into those details and you can refer to [6] for complete details. The "Advice' provides the logic that is to be executed while when to execute this logic is provided by what is called 'PointCut'. A 'PointCut' is a combination of 'JoinPoints' which is described for a java method at which point the Aspect 'Advice' must be executed. In short, consider 'PointCut or JoinPoint' to be when, while 'Advice' to be what to be executed. For more details please refer to below [6]. Simple examples for the same are provided in [7].

    Below is a simple example for Logging. The below is an Aspect that when called, prints out the JoinPoint details before executing the java method that is configured to execute the log() method below. The method jp.proceed() will give the program handle back to the java method and when done, the program handle comes back to print another log statement. The below method log() takes the param ProceedingJoinPoint object. This object can only be used when the 'Advice=around' as you may note in the below Application Context XML file.

    package org.spring.learn.class1;

    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.Pointcut;


    public class LoggingAspect {

    /** this method can only be executed with Advice=around since the arg ProceedingJoinPoint is used. */
    public Object log(ProceedingJoinPoint jp) throws Throwable {

    System.out.println("LoggingAspect: entering log method= " + jp.toShortString()
    + " WITH PARAMS= " + jp.getArgs());
    Object point = jp.proceed();

    System.out.println("LoggingAspect: exiting log method= " + jp.toShortString()
    + " WITH RETURN AS= " + point);

    return point;
    }

    /** since this method does not take any JoinPoint arg, it can be executed before or after the method execution */
    public void log1 () {
    System.out.println("LoggingAspect: exiting log1 method= ");
    }
    }


    The application context XML file is as 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:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

    <context:property-placeholder location="resource/config/**/db.properties"/>

    <!-- db access -->
    <bean id="dbDataReaderUsingPropertyHolder" class="org.spring.learn.class1.DBDataReaderUsingPropertyHolder">
    <property name="dataSource" ref="datasource"/>
    </bean>

    <bean id="datasource"
    class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close">
    <property name="driverClassName" value="${driver}"/>
    <property name="url" value="${url}"/>
    <property name="username" value="${user}"/>
    <property name="password" value="${password}"/>
    </bean>

    <!-- Logging Aspect -->
    <bean id="loggingAspectBean" class="org.spring.learn.class1.LoggingAspect"/>

    <aop:config>
    <aop:aspect ref="loggingAspectBean">
    <!-- point cut expression - defines expression that is to be matched for the execution of the Aspect -->
    <aop:pointcut id="logPointCut" expression="execution(* org.spring.learn.class1.DB*.*(..))"/>
    <!-- advice for pointcut i.e when the pointcut is reached the code to be executed. -->
    <aop:before pointcut-ref="logPointCut" method="log1"/>

    <!-- using 'within' JoinPoint expression and 'around' advice'
    <aop:pointcut id="logWithinPointCut" expression="within(org.spring.learn.class1.DB*)"/>
    <aop:around pointcut-ref="logWithinPointCut" method="log"/>
    -->
    </aop:aspect>
    </aop:config>
    </beans>

Ref:
[1] http://martinfowler.com/bliki/InversionOfControl.html
[2] http://martinfowler.com/articles/injection.html#InversionOfControl
[3] http://www.devx.com/Java/Article/21665/0/page/4
[4] http://www.parleys.com/display/PARLEYS/Home#talk=4358355;slide=18;title=How%20to%20build%20Enterprise%20Java%20applications%20with%20Spring
[5] http://www.java2s.com/Code/Java/Spring/SetupDataSourceforOracle.htm
[6] http://static.springframework.org/spring/docs/2.5.x/reference/aop.html
[7] http://www.javaworld.com/javaworld/jw-01-2007/jw-0105-aop.html?page=3
[8] http://static.springframework.org/spring/docs/2.5.x/reference/