• No results found

PART-III

In document SPRING Framework (Page 22-43)

(PUBLISHED IN DEVELOPER IQ - September2005)

Now we will move on to the main process of any enterprise application: Data Persistence.

For this we have to initialize our data access framework, manage resources, handle various exceptions and if anything goes wrong, we must roll-back so as to save the existing data.

Spring comes with a family of data access frameworks that integrates well will variety of data access technologies like JDBC, Java Data Objects and Object Relational Mapping (ORM) tools like Hibernate, OJB, iBatis etc.,

Many J2EE application servers and even web servers provide a 'dataSource' via Jndi name. To configure the spring bean with the Jndi name of our 'dataSource' and use its connection pooling facility 'JndiObjectFactoryBean' is used. When a DataSource is not present, we need a connection pooling bean that implements 'dataSource'. For this

purpose we use 'dbcp.BasicDataSource' is used. By using this we can have a 'dataSource' with connection pooling independent of application server.

To perform unit-tests in our data access code, spring comes with a very lightweight 'dataSource' implementation class: 'DriverManagerDataSource'. This class can be easily configured for unit tests as,

DriverManagerDataSource dataSource = new DriverManagerDataSource();

dataSource.setDriverClassName(driver);

dataSource.setUrl(url);

dataSource.setUsername(username);

dataSource.setPassword(password);

These properties can be configured in the spring configuration file also.

---

Spring comes with its own data access framework. Spring separates the fixed and variant parts of data access process into two distinct classes : template and callback. Template manages the fixed part of our framework like data connection, managing resources, controlling transaction etc., while the Callback defines the things that are specific to our application like creating statements, binding parameters etc.,

The template class of Spring is 'JdbcTemplate'. A 'dataSource' is provided inside JdbcTemplate.

An example of database connection using 'JdbcTemplate' is shown below. Here we are using 'MySql' database. The MySql database can be downloaded from

http://www.mysql.com. Download mysql4.1 and MyODBC-3.51 (ODBC Connector) install these in the hard disk. For Mysql give a username('root') and a password ('sql').

Then start the 'My Sql Console Line Client' from programs and type the password.

The prompt will be changed to mysql, mysql> show databases;

Two databases will be present default: mysql and test.

mysql> use test;

We will get message as 'Database changed'. Next create table in test database as follows mysql> create table table1(name text, place text);

We will get the message 'Query OK, 0 rows affected'. Now we have created a table in mysql database, set the path and classpath as before and edit the program

---f:\sprindemo\datacon.java

import javax.sql.*;

public interface datacon {

public DataSource dbcon();

}

--- f:\sprindemo\dataconimpl.java

import org.springframework.jdbc.core.*;

import org.springframework.jdbc.datasource.*;

import org.springframework.jdbc.object.*;

import org.springframework.jdbc.support.*;

import javax.sql.*;

public class dataconimpl implements datacon {

private DataSource dataSource;

public void setDataSource(DataSource ds) {

dataSource = ds;

}

public DataSource dbcon() {

return dataSource;

} }

--- f:\sprindemo\datacon.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"

"http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

<bean id="dataSource"

class="org.springframework.jdbc.datasource.DriverManagerDataSource">

<property name="driverClassName">

<value>sun.jdbc.odbc.JdbcOdbcDriver</value>

</property>

<property name="url">

<value>jdbc:odbc:test</value>

</property>

<property name="username">

<value>root</value>

</property>

<property name="password">

<value>sql</value>

</property>

</bean>

<bean id="datacon" class="dataconimpl">

<property name="dataSource">

<ref local="dataSource"/>

</property>

</bean>

</beans>

--- f:\sprindemo\springservlet.java import java.io.*;

import javax.sql.*;

import java.sql.*;

import java.util.*;

import javax.servlet.*;

import javax.servlet.http.*;

import org.springframework.beans.factory.*;

import org.springframework.beans.factory.xml.*;

import org.springframework.core.io.*;

import org.springframework.jdbc.core.*;

import org.springframework.jdbc.datasource.*;

import org.springframework.jdbc.object.*;

import org.springframework.jdbc.support.*;

public class springservlet extends HttpServlet {

public void doPost(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException {

resp.setContentType("text/html");

PrintWriter out = resp.getWriter();

String a = req.getParameter("text1");

String b = req.getParameter("text2");

String c = req.getParameter("combo1");

String d = req.getParameter("combo2");

try {

System.out.println("Wait...");

Resource res = new ClassPathResource("datacon.xml");

BeanFactory factory = new XmlBeanFactory(res);

datacon bean1 = (datacon)factory.getBean("datacon");

DataSource ds=bean1.dbcon();

if(d.equals("add")) {

JdbcTemplate jt = new JdbcTemplate(ds);

jt.execute("insert into table1 values('"+a+"','"+b+"') ");

out.println("Record Added");

}

if(d.equals("delete")) {

JdbcTemplate jt = new JdbcTemplate(ds);

jt.execute("delete from table1 where name='"+a+"' ");

out.println("Record Deleted");

}

if(d.equals("find")) {

List list1;

JdbcTemplate jt = new JdbcTemplate(ds);

list1=jt.queryForList("select * from table1 where name='"+a+"'");

Iterator i=list1.iterator();

while(i.hasNext()) {

Object ob = i.next();

out.println(ob.toString());

} }

if(d.equals("update")) {

if(c.equals("name")) {

JdbcTemplate jt = new JdbcTemplate(ds);

jt.execute("update table1 set table1.place='"+b+"'where table1.name='"+a+"' ");

}

if(c.equals("place")) {

JdbcTemplate jt = new JdbcTemplate(ds);

jt.execute("update table1 set table1.name='"+a+"'where table1.place='"+b+"' ");

}

out.println("Record Updated");

} }

catch(Exception e1)

{System.out.println(""+e1);}

} }

--- f:\sprindemo\springservlet.htm

<html>

<body bgcolor="pink">

<form method=post

action="http://localhost:8080/

servlet/springservlet">

Name : <input type=text name="text1"> <br><br>

Place : <input type=text name="text2"> <br><br>

Criterion :

<select name="combo1" size=1>

<option value="name">Name <option value="place">Place

</select> <br><br>

<select name="combo2" size=1>

<option value="add">Add <option value="delete">Remove <option value="find">Find <option value="update">Update </select> <br><br>

<input type=submit>

</form>

</body>

</html>

The deployment procedure is same as before compile the all the files datacon.java, dataconimpl.java and springservlet.java and copy all the class files and the xml file datacon.xml to g:\tomcat5\webapps\root\web-inf\classes. Copy the html file to g:\tomcat5\webapps\root. Add entry to web.xml file.

Start Tomcat server and open browser

and type url as http://localhost:8080/ servletclient.htm. We will get a two textboxes, two comboboxes and a 'submit' button. Type name and place in textboxes, select 'add' from combobox and click 'submit' button. We will get message as 'Record Added'

---

Spring provides integration for many of the ORM frameworks like Hibernate, JDO, Apache OJB and iBATIS SQL Maps.

For mapping the hibernate resources, an instance of 'SessionFactory' is needed, 'LocalSessionFactoryBean' is used for this purpose and its properties

'hibernateProperties', 'mappingResources' and 'mappingDirectoryLocation' are set.

Like Spring's DAO framework, here we have 'HibernateTemplate' to create an object of 'SessionFactory'. To access the data with 'HibernateTemplate'

'execute(HibernateCallback)' method is used.

Similar to the 'SessionFactory' of hibernate, JDO has 'PersistenceManager Factory'. It can be configured by using 'LocalPersistenceManagerFactoryBean'. Also

'JDOTemplate' to create an object of 'PersistenceManagerFactory'. To access the data with 'JDOTemplate' 'execute(JDOCallback)' method is used.

For iBATIS, we have to configure a 'SQLMapClient' by using

'SQLMapClientFactoryBean' and its properties 'configLocation' and 'dataSource' are set. Here also we have 'SQLMapClientTemplate'.

To access the data 'execute(SQLMapClientCallback)' method is used.

The only property that we need to change to integrate Spring with OJB is 'ConnectionFactoryClass' and it is done by using

'LocalDataSourceConnectionFactory'.

In the next article we shall see how to use a RMI service in Spring and how to export any Spring managed bean as RMI.

---

SPRING ... REMOTING

by Farihah Noushene B.E.,

PART-IV

(PUBLISHED IN DEVELOPER IQ - September2005)

Spring supports remoting for six different RPC models:

1. Remote Method Invocation (RMI) 2. Hessian

3. Burlap

4. HTTP invoker 5. EJB

6. JAX-RPC

In all the models, services are configured into the application through spring configuration file as spring managed beans. This is accomplished by using a proxy factory bean that enable us to wire remote services into the properties of our beans as if they were local objects.

Spring provides 'RmiProxyFactoryBean' to use the RMI service and

'RmiServiceExporter' to export any spring managed bean as a RMI service.

For wiring a Hessian based service to Spring client, Spring's 'HessianProxyFactory Bean' is used.

To export a Hessian Service 'HessianServiceExporter' is used and similarly for wiring a Burlap service 'BurlapProxyFactoryBean' is used and 'BurlapServiceExporter' is used to export a burlap service.

For exporting beans as HTTP invoker services, 'HttpInvokerServiceExporter' is used .To access an HTTP invoker service 'HttpInvokerProxyFactoryBean' can be used.

Spring provides two proxy factory beans to access the Enterprise Java Beans.

'LocalStatelessSessionProxyFactoryBean' is used to access the EJB in the same container(local) and another one is

'SimpleRemoteStatelessSessionProxyFactoryBean' which is used to access the remote EJBs.

For all the above models spring provides service exporter classes that exports Java Beans as remote service. Spring does not provide any EJB Service Exporter and it provides four abstract support classes to make the development of Spring enabled EJB. They are 1. AbstractMessageDrivenBean to develop MDBs that accept sources other than JMS.

2. AbstractJmsMessageDrivenBean to develop MDBs that accept messages from JMS sources.

3. AbstractStatelessSessionBean to develop stateless session bean.

4. AbstractStstefulSessionBean to develop stateful session bean.

'JaxRpcPostProxyFactoryBean' is used to wire a web service into the spring application.

The client makes calls to the proxy to provide the service and the proxy calls the remote service on behalf of the client.

---

Now we shall see how to wire other RMI services into spring application and also how to export our own service.

Remote Method Invocation (RMI) Model:

RMI was first introduced in JDK 1.1. But developing and accessing RMI services involves various steps and also have lookups which makes the code hard to test. Spring simplifies the RMI by providing a 'proxy factory bean' that enables us to wire the RMI services into spring application as if they were local beans. Spring also provides a remote exporter that converts our 'spring managed beans' into RMI services.

Spring's 'RmiProxyFactoryBean' is a factory bean that creates a proxy to RMI service.

It is declared spring configuration file under the <bean> tag as follows,

<bean id="service1"

class="org.springframework.remoting.rmi.RmiProxyFactoryBean">

<property name="serviceUrl">

<value>rmi://${hostname}/service1</value>

</property>

<property name="serviceInterface">

<value>service1</value>

</property>

</bean>

The url of the RMI service is set through the 'serviceUrl' property. The

'serviceInterface' property specifies the interface that the service implements and only through that the client invokes methods on the service.

For using the service the implementation code is wired to the RMI using the following code,

<bean id="serviceimpl" class="serviceimpl">

<property name="service1">

<ref bean="service1"/>

</property>

</bean>

---

First set the path and classpath as before. Next edit the RMI service.

//f:\springdemo\rmserver.java import java.rmi.*;

public interface rmserver extends Remote {

String getresult(String s) throws RemoteException;

}

---

//f:\springdemo\rmserverimpl.java import java.rmi.*;

import java.rmi.server.*;

public class rmserverimpl extends UnicastRemoteObject implements rmserver

{

public static void main(String args[]) {

try {

rmserverimpl ob = new rmserverimpl();

Naming.rebind("rmserver",ob);

System.out.println("ready");

}

catch(Exception e1)

{System.out.println(""+e1);}

}

public rmserverimpl() throws RemoteException {

System.out.println("constructor ok");

}

public String getresult(String a) throws RemoteException {

return "Hai..."+a;

} }

--- //f:\springdemo\rmserver.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"

"http://www.springframework.org/dtd/

spring-beans.dtd">

<beans>

<bean id="rmserver"

class="org.springframework.remoting.rmi.RmiProxyFactoryBean">

<property name="serviceUrl">

<value>rmi://localhost/rmserver</value>

</property>

<property name="serviceInterface">

<value>rmserver</value>

</property>

</bean>

<bean id="rmserverimpl" class="rmserverimpl">

<property name="rmserver">

<ref bean="rmserver"/>

</property>

</bean>

</beans>

--- //f:\springdemo\rmspring.java

import java.rmi.*;

import org.springframework.beans.factory.*;

import org.springframework.beans.factory.xml.*;

import org.springframework.core.io.*;

public class rmspring {

public static void main(String args[]) {

try {

System.out.println("Wait..");

Resource res = new ClassPathResource("rmi.xml");

BeanFactory factory = new XmlBeanFactory(res);

rmserver bean1 = (rmserver) factory.getBean("rmserver");

String r=bean1.getresult(args[0]);

System.out.println(r);

}

catch(Exception e1)

{System.out.println(""+e1);}

} }

--- To run:

f:\springdemo>javac rmserver.java f:\springdemo>javac rmserverimpl.java

f:\springdemo>rmic rmserverimpl (To create stub and skeleton) f:\springdemo>javac rmspring.java

f:\springdemo>start rmiregistry (a blank window will appear) f:\springdemo>java rmserverimpl

Open another Window and run the client code by giving the argument f:\springdemo>java rmspring "sam"

We will get the output as:

Wait..

...

Hai... sam

Here we have removed the 'lookup' code in the client side.

---

Spring also supports the server side of RMI. Here the service itself is written with spring and it is exposed as an RMI service. Here the bean is written as a simple JavaBean. Also we need not generate the stub and skeleton using 'rmic' command and manually add it to RMI registry. Instead of these traditional procedure 'RmiServiceExporter' is used to export any Spring managed bean as an RMI service. It wrapps the bean in an adapter class. The adapter class is then bound to RMI registry and the proxies request the service.

<bean class="org.springframework.remoting.rmi.RmiServiceExporter">

<property name="service1">

<ref bean="service1"/>

</property>

<property name="serviceName">

<value>service1</value>

</property>

<property name="serviceInterface">

<value>service1</value>

</property>

</bean>

The 'serviceName property' indicates the name of service and 'serviceInterface' specifies the interface implemented by the service. There is no need of 'serviceUrl' here

First set the path and classpath as before. Next edit the service.

//f:\springdemo\rmservice.java public interface rmservice {

String getresult(String s);

}

--- //f:\springdemo\rmserviceimpl.java

public class rmserviceimpl implements rmservice {

public static void main(String args[]) {

System.out.println("ready");

}

public rmserviceimpl() {

System.out.println("constructor ok");

}

public String getresult(String a) {

return "Hai"+a;

} }

--- //f:\springdemo\rmservice.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"

"http://www.springframework.org/dtd/ spring-beans.dtd">

<beans>

<bean class="org.springframework.remoting.rmi.RmiServiceExporter">

<property name="service">

<value>rmservice</value>

</property>

<property name="serviceName">

<value>service1</value>

</property>

<property name="serviceInterface">

<value>rmservice</value>

</property>

</bean>

<bean id="rmservice" class="rmserviceimpl">

</bean>

</beans>

--- //f:\springdemo\rmserviceclient.java import java.io.*;

import org.springframework.beans.factory.*;

import org.springframework.beans.factory.xml.*;

import org.springframework.core.io.*;

class rmserviceclient {

public static void main(String args[]) {

try {

System.out.println("Wait..");

Resource res = new ClassPathResource("rmservice.xml");

BeanFactory factory = new XmlBeanFactory(res);

System.out.println("factory created");

rmservice bean1 = (rmservice)factory.getBean("rmservice");

String s = bean1.getresult(args[0]);

System.out.println(s);

}

catch(Exception e1)

{System.out.println(""+e1);}

} }

--- To run:

f:\springdemo>javac rmservice.java f:\springdemo>javac rmserviceimpl.java f:\springdemo>javac rmserviceclient.java f:\springdemo>java rmsserviceclient We will get Output as:

Wait..

Aug 12, 2002 10:55:07 PM

org.springframework.beans.factory.

xml.XmlBeanDefinitionReader loadBeanDefinitions

INFO: Loading XML bean definitions from class path resource[rmservice.xml]

Aug 12, 2002 10:55:07 PM

org.springframework.beans.factory.

support.AbstractBeanFactory getBean INFO: Creating shared instance of singleton bean 'rmservice' constructor ok

Hai...sam

Here the service interface doesn't extend the 'java.rmi.Remote' method and 'RemoteException' is not thrown by the methods. There is no binding in the

implementation code. Also we can direcly run the client. No run to run 'rmserverimpl' first. Also there is no need to run the RMI registry.

---

In document SPRING Framework (Page 22-43)

Related documents