http://veerasundar.com/blog/2009/04/aspect-oriented-programming-using-spring-aop-an-introduction-part-2/
http://sivalabs.blogspot.com/2011/01/aspect-oriented-programming-using.html
Sometimes it required to call a (non-static) method in the bean only-once at the ApplicationContext load up, just to initialize the bean components. So you may inject some parameters by setters or constructors, but than you may have some other fields, which have to instantiated from those fields or separately like from some local file.
So for this various approaches are available. See here for these approaches.
Consider the Student service example we saw here. Also note the approach of doing the same thing by using @PostConstruct and @PreDestroy annotations.
Service Bean:
public class StudentService {
String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public void initIt() throws Exception {
System.out.println("After properties has been set : " + message);
//do some initialization
}
public void cleanUp() throws Exception {
System.out.println("Cleaned Everyting");
}
}
Bean config file (initMethod.xml):
<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.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<!-- our bean here -->
<bean id="studentService" class="com.xxxx.StudentService"
init-method="initIt" destroy-method="cleanUp">
<property name="message" value="property message" />
</bean>
<beans>
Running the program:
public class Runner
{
public static void main( String[] args )
{
ConfigurableApplicationContext context =
new ClassPathXmlApplicationContext(new String[] {"initMethod.xml"});
StudentService stud =
(StudentService)context.getBean("studentService");
System.out.println(stud );
context.close();
}
}
Sometimes it required to call a (non-static) method in the bean only-once at the ApplicationContext load up, just to initialize the bean components. So you may inject some parameters by setters or constructors, but than you may have some other fields, which have to instantiated from those fields or separately like from some local file.
So for this various approaches are available. See here for these approaches.
Useful when using component scanning to autodetect beans.
Makes it clear that a specific method is to be used for initialisation
Cons:
Initialisation no longer centrally specified in configuration. Now scattered throughout code.
SimpleJdbcTemplate simpleJdbcTemplate = new
SimpleJdbcTemplate(dataSource);
public void insertBatch(final List<Flight> flightList){
String sql = "INSERT INTO flights_test " +
"(flight_no, carrier, kahase,kahatak) VALUES (?, ?, ?,?)";
List<Object[]> paramList = new ArrayList<Object[]>();
for (Flight flight : flightList) {
paramList.add(new Object[] {flight.getFlightNo(),
flight.getCarrier(), flight .getFrom(), flight.getTo()}
);
}
simpleJdbcTemplate.batchUpdate(sql, parameters);
}
Calling the above function:
Flight flight1 = new Flight("JL-220", "Jet
Airways","Mumbai","Jaipur");
Flight flight2= new Flight("KL-
202", "Kingfisher","Jaipur","Agra");
Flight flight3= new Flight("AI-220", "Air
India","Agra","Delhi");
List<Flight> flights = new ArrayList<Flight>();
flights.add(flight1);
flights.add(flight2);
flights.add(flight3);
flightDao.insertBatch(flights);
An Application Server is any server that supplies additional functionality related to enterprise computing -- for instance, load balancing, database access classes, transaction processing, messaging, and so on.
As for the application server, according to our definition, an application server exposes business logic to client applications through various protocols, possibly including HTTP. While a Web server mainly deals with sending HTML for display in a Web browser, an application server provides access to business logic for use by client application programs. The application program can use this logic just as it would call a method on an object (or a function in the procedural world).
Such application server clients can include GUIs (graphical user interface) running on a PC, a Web server, or even other application servers. The information traveling back and forth between an application server and its client is not restricted to simple display markup. Instead, the information is program logic. Since the logic takes the form of data and method calls and not static HTML, the client can employ the exposed business logic however it wants.
In most cases, the server exposes this business logic through a component API, such as the EJB (Enterprise JavaBeans) component model found on J2EE (Java 2 Platform, Enterprise Edition) application servers. Moreover, the application server manages its own resources. Such gate-keeping duties include security, transaction processing, and resource pooling, and messaging. Like a Web server, an application server may also employ various scalability and fault-tolerance techniques.
The web server may need to execute an application in response to the user’s request. It may be generating a list of news items, or handling a form submission to a guest book. If the server application is written as a Java Servlet, it will need a place to execute, and this place is typically called a Servlet Engine
EJB Application Servers provide an EJB container, which is the environment that beans will execute in, and this container will manage transactions, thread pools, and other issues as necessary. These application servers are usually stand-alone products, and developers would tie their servlets/JSP pages to the EJB components via remote object access APIs. Depending on the application server, programmers may use CORBA or RMI to talk to their beans, but the baseline standard is to use JNDI to locate and create EJB references as necessary.
WebLogic contains a web server, servlet engine, JSP processor, JMS facility, as well as an EJB container.
An Application Server = Web Server + EJB Container + middle ware services(resources Such gate-keeping duties include security, transaction processing, and resource pooling, and messaging)
The Java Enterprise Edition Application servers are:
BEA WebLogic server,Red Hat JBoss, IBM WebSphere Application server, Glassfish Application server.
A Web server serves pages for viewing in web browser, application server provides exposes business logic for client applications through various protocols .Web server exclusively handles http requests.
- A Web Server (otherwise known as an HTTP Server)
An Application Server is any server that supplies additional functionality related to enterprise computing -- for instance, load balancing, database access classes, transaction processing, messaging, and so on.
A Web Server understands and supports only HTTP protocol whereas an Application Server supports HTTP, TCP/IP and many more protocols. Also many more features such as Caches, Clusters, and Load Balancing are there in Application Servers which are not available in Web Servers. We can also Configure Application Servers to work as Web Server.
In short, Application Server is a super set of which Web Server is a sub set.
BeanFactory factory = new XmlBeanFactory(
new InputStreamResource(
new FileInputStream("beans.xml"))); // 1
Employee emp = (Employee) factory.getBean("employeeBean"); // 2
ApplicationContext context =
new ClassPathXmlApplicationContext("beans.xml"); // 1
Employee emp = (Employee) context.getBean("employeeBean"); // 2
In this article, I will show you that Spring dependency injection mechanism is not restricted solely to Spring-managed beans, that is Spring can inject its beans in objects created by the new
keywords, servlets instantiated in the servlet container, and pretty anything you like. Spring classical mode is to be an object factory. That is, Spring creates anything in your application, using the provided constructor. Yet, some of the objects you use are outer Spring’s perimeter. Two simple examples:
new
keyword Both these examples show you can’t delegate to Spring every object instantiation.
There was a time when I foolishly thought Spring was a closed container. Either your beans were managed by Spring, or they didn’t: if they were, you could inject them with other Spring-managed beans. If they weren’t, tough luck! Well, this is dead wrong. Spring can inject its beans into pretty much anything provided you’re okay to use AOP.
In order to do this, there are only 2 steps to take:
It is done in your Spring configuration file.
<?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">
<This does the magic />
<context:spring-configured />
<-- These are for classical annotation configuration -->
<context:annotation-config />
<context:component-scan base-package="com.vaani.spring.outcontainer" />
</beans>
You need also configure which aspect engine to use to weave the compiled bytecode. In this case, it is AspectJ, which is the AOP component used by Spring. Since i’m using Maven as my build tool of choice, this is easily done in my POM. Ant users will have to do it in their build.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
...
<properties>
<spring-version>2.5.6.SEC01</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.5.4</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<configuration>
<complianceLevel>1.5</complianceLevel>
<aspectLibraries>
<aspectLibrary>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</aspectLibrary>
</aspectLibraries>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
This is done with the @org.springframework.beans.factory.annotation.Configurable
annotation on your injectable object.
@Configurable
public class DomainObject {
/** The object to be injected by Spring. */
private Injectable injectable;
public Injectable getInjectable() {
return injectable;
}
@Autowired
public void setInjectable(Injectable injectable) {
this.injectable = injectable;
}
}
Now with only these few lines of configuration (no code!), I’m able to inject Spring-managed beans into my domain object. I leave to you to implement the same with regular servlets (which are much harder to display as unit test).
You can find the Maven project used for this article here. The unit test packaged shows the process described above.
To go further:
The Spring framework provides extensive support for data access through the use of support classes (JdbcDaoSupport, JdbcTemplate etc.), and extensive exception hierarchy to wrap any platform specific SQLException into an exception in the spring exception hierarchy. Additionally Spring framework also provides good support for integrating with ORM technologies like Hibernate and iBatis etc.
1. Create the entity bean: The bean here represents a simple stock quote
package com.vaani.entity;
public class StockQuoteBean {
private String quoteId;
private String stockSymbol;
private String name;
public String getQuoteId() {
return quoteId;
}
public void setQuoteId(String quoteId) {
this.quoteId = quoteId;
}
public String getStockSymbol() {
return stockSymbol;
}
public void setStockSymbol(String stockSymbol) {
this.stockSymbol = stockSymbol;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
2. Create a Hibernate Mapping file (hbm) for the entity:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.vaani.entity.StockQuoteBean" table="STOCK_QUOTES" lazy="false">
<id name="quoteId" column="quote_id">
<generator class="assigned" />
</id>
<property name="stockSymbol">
<column name="stock_symbol" />
</property>
<property name="name">
<column name="name" />
</property>
</class>
</hibernate-mapping>
The one important thing to note here is that in the declaration, a [lazy="false"] has been added to the mapping for the stockquote bean. The reason for this is that in hibernate 3, lazy initialization is turned on by default. This raises a problem when used with spring's HibernateCallback. The spring HibernateTemplate.execute() by default closes any open sessions upon completion. When used with lazy initialization you may get a LazyInitializationException like the following
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
If you want to use lazy initialization with HibernateCallback, you will have to use this within a transaction context. The javadoc for HibernateTemplate specifies this explicitly.
Note that operations that return an Iterator (i.e. iterate) are supposed
to be used within Spring-driven or JTA-driven transactions (with
HibernateTransactionManager, JtaTransactionManager, or EJB CMT). Else, the
Iterator won't be able to read results from its ResultSet anymore, as the
underlying Hibernate Session will already have been closed.
Lazy loading will also just work with an open Hibernate Session, either within a
transaction or within OpenSessionInViewFilter/Interceptor. Furthermore, some
operations just make sense within transactions, for example: contains, evict,
lock, flush, clear.
3. Create the service class: The service class simply acts as an intermediary between the client and the DAO classes.
package com.vaani.springhibernate;
import com.vaani.entity.StockQuoteBean;
import com.vaani.hibernate.dao.PortfolioDAO;
public class PortfolioService {
private PortfolioDAO portfolioDAO;
public StockQuoteBean getStockQuote(String id) {
StockQuoteBean result = portfolioDAO.getStockQuote(id);
return result;
}
public void updateStockQuote(StockQuoteBean stockQuoteBean) {
portfolioDAO.updateStockQuote(stockQuoteBean);
}
public PortfolioDAO getPortfolioDAO() {
return portfolioDAO;
}
public void setPortfolioDAO(PortfolioDAO portfolioDAO) {
this.portfolioDAO = portfolioDAO;
System.out.println("Setting portfolio DAO to : " + portfolioDAO.getClass());
}
}
4. The DAO interface:
package com.vaani.hibernate.dao;
import com.vaani.entity.StockQuoteBean;
public interface PortfolioDAO {
public StockQuoteBean getStockQuote(String id);
public void updateStockQuote(StockQuoteBean bean);
public StockQuoteBean getStockQuote_hibernateTemplate(String id);
public void updateStockQuote_hibernateTemplate(StockQuoteBean bean);
}
5. The DAO Classes: The DAO classes shows the different ways in which the Hibernate calls can be made using the Spring support classes. There are three primary ways in which these calls can be made
All these methods will be explained when used in the following sections.
Using HibernateTemplate
package com.vaani.hibernate.dao;
import java.sql.SQLException;
import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;
import beans.StockQuoteBean;
public class PortfolioDAOTemplate implements PortfolioDAO{
private HibernateTemplate hibernateTemplate;
public PortfolioDAOTemplate() {
System.out.println("Init transaction dao");
}
public StockQuoteBean getStockQuote(final String id) {
HibernateCallback callback = new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException, SQLException {
return session.load(StockQuoteBean.class, id);
}
};
return (StockQuoteBean) hibernateTemplate.execute(callback);
}
public void updateStockQuote(final StockQuoteBean StockQuoteBean) {
HibernateCallback callback = new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException, SQLException {
session.saveOrUpdate(StockQuoteBean);
return null;
}
};
hibernateTemplate.execute(callback);
}
public void updateStockQuote_hibernateTemplate(StockQuoteBean StockQuoteBean) {
hibernateTemplate.update(StockQuoteBean);
}
public StockQuoteBean getStockQuote_hibernateTemplate(String id) {
List<StockQuoteBean> transactions = hibernateTemplate.find("from beans.StockQuoteBean stockQuoteBean where stockQuoteBean.quoteId=?", id);
return transactions.get(0);
}
public HibernateTemplate getHibernateTemplate() {
return hibernateTemplate;
}
public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
this.hibernateTemplate = hibernateTemplate;
}
}
package com.vaani.hibernate.dao;This class uses HibernateDaoSupport to get instances of HibernateTemplate, and the Hibernate Session. The getStockQuote() and updateStockQuote() in this class make calls to hibernate session directly.
import java.util.List;
import org.hibernate.Query;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import beans.StockQuoteBean;
public class PortfolioDAOSupport extends HibernateDaoSupport implements PortfolioDAO {
public void updateStockQuote(StockQuoteBean stockQuoteBean) {
Query query = getSession().createQuery("update beans.StockQuoteBean set stockSymbol=? where quoteId=?");
query.setString(0, stockQuoteBean.getStockSymbol());
query.setString(1, stockQuoteBean.getQuoteId());
query.executeUpdate();
}
public StockQuoteBean getStockQuote(String id) {
Query query = getSession().createQuery("from beans.StockQuoteBean stockQuoteBean where stockQuoteBean.quoteId=?");
query.setString(0, id);
List results = query.list();
if(results == null || results.size() == 0) {
throw new RuntimeException("No result");
}
return (StockQuoteBean)results.get(0);
}
public void updateStockQuote_hibernateTemplate(StockQuoteBean StockQuoteBean) {
getHibernateTemplate().update(StockQuoteBean);
}
public StockQuoteBean getStockQuote_hibernateTemplate(String id) {
List<StockQuoteBean> transactions = getHibernateTemplate().find("from beans.StockQuoteBean stockQuoteBean where stockQuoteBean.quoteId=?", id);
return transactions.get(0);
}
}
<?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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<bean id="portfolioDAOTemplate" class="com.vaani.hibernate.dao.PortfolioDAOTemplate">
<property name="hibernateTemplate" ref="hibernateTemplate" />
</bean>
<bean id="portfolioDAOSupport" class="com.vaani.hibernate.dao.PortfolioDAOSupport">
<property name="hibernateTemplate" ref="hibernateTemplate" />
</bean>
<bean id="portfolioService" class="com.vaani.springhibernate.PortfolioService">
<property name="portfolioDAO" ref="portfolioDAOSupport"></property>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:@localhost:1521/xe" />
<property name="username" value="appUser" />
<property name="password" value="password" />
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mappingResources">
<list>
<value>stockquote.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.generate_statistics">true</prop>
</props>
</property>
</bean>
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
</beans>
7 . The main class
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import com.vaani.entity.StockQuoteBean;
public class SpringHibernateTest {
public static void main(String[] args) {
Resource resource = new FileSystemResource("applicationContext.xml");
BeanFactory factory = new XmlBeanFactory(resource);
PortfolioService portfolioService = (PortfolioService) factory.getBean("portfolioService");
StockQuoteBean result = portfolioService.getStockQuote("123");
System.out.println(result.getStockSymbol());
empResult.setStockSymbol("GOOG");
portfolioService.updateStockQuote(result);
}
}
1) There should be one no argument constructor
2) The class should implement the java.io.Serializable interface
3) There should be getter and setter methods for properties which are declared as private.