You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
453 lines
22 KiB
453 lines
22 KiB
<?xml version="1.0" encoding="UTF-8"?> |
|
<!DOCTYPE appendix PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" |
|
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd"> |
|
<appendix id="classic-spring"> |
|
<title>Classic Spring Usage</title> |
|
|
|
<para>This appendix discusses some classic Spring usage patterns as a |
|
reference for developers maintaining legacy Spring applications. These usage |
|
patterns no longer reflect the recommended way of using these features and |
|
the current recommended usage is covered in the respective sections of the |
|
reference manual.</para> |
|
|
|
<section id="classic-spring-orm"> |
|
<title>Classic ORM usage</title> |
|
|
|
<para>This section documents the classic usage patterns that you might |
|
encounter in a legacy Spring application. For the currently recommended |
|
usage patterns, please refer to the <xref linkend="orm" /> chapter.</para> |
|
|
|
<section id="classic-spring-hibernate"> |
|
<title>Hibernate</title> |
|
|
|
<para>For the currently recommended usage patterns for Hibernate see |
|
<xref linkend="orm-hibernate" /></para> |
|
|
|
<section id="orm-hibernate-template"> |
|
<title>The <classname>HibernateTemplate</classname></title> |
|
|
|
<para>The basic programming model for templating looks as follows, for |
|
methods that can be part of any custom data access object or business |
|
service. There are no restrictions on the implementation of the |
|
surrounding object at all, it just needs to provide a Hibernate |
|
<interfacename>SessionFactory</interfacename>. It can get the latter |
|
from anywhere, but preferably as bean reference from a Spring IoC |
|
container - via a simple |
|
<methodname>setSessionFactory(..)</methodname> bean property setter. |
|
The following snippets show a DAO definition in a Spring container, |
|
referencing the above defined |
|
<interfacename>SessionFactory</interfacename>, and an example for a |
|
DAO method implementation.</para> |
|
|
|
<programlisting language="xml"><beans> |
|
|
|
<bean id="myProductDao" class="product.ProductDaoImpl"> |
|
<property name="sessionFactory" ref="mySessionFactory"/> |
|
</bean> |
|
|
|
</beans></programlisting> |
|
|
|
<programlisting language="java">public class ProductDaoImpl implements ProductDao { |
|
|
|
private HibernateTemplate hibernateTemplate; |
|
|
|
public void setSessionFactory(SessionFactory sessionFactory) { |
|
this.hibernateTemplate = new HibernateTemplate(sessionFactory); |
|
} |
|
|
|
public Collection loadProductsByCategory(String category) throws DataAccessException { |
|
return this.hibernateTemplate.find("from test.Product product where product.category=?", category); |
|
} |
|
}</programlisting> |
|
|
|
<para>The <classname>HibernateTemplate</classname> class provides many |
|
methods that mirror the methods exposed on the Hibernate |
|
<interfacename>Session</interfacename> interface, in addition to a |
|
number of convenience methods such as the one shown above. If you need |
|
access to the <interfacename>Session</interfacename> to invoke methods |
|
that are not exposed on the <classname>HibernateTemplate</classname>, |
|
you can always drop down to a callback-based approach like so.</para> |
|
|
|
<programlisting language="java">public class ProductDaoImpl implements ProductDao { |
|
|
|
private HibernateTemplate hibernateTemplate; |
|
|
|
public void setSessionFactory(SessionFactory sessionFactory) { |
|
this.hibernateTemplate = new HibernateTemplate(sessionFactory); |
|
} |
|
|
|
public Collection loadProductsByCategory(final String category) throws DataAccessException { |
|
return this.hibernateTemplate.execute(new HibernateCallback() { |
|
|
|
public Object doInHibernate(Session session) { |
|
Criteria criteria = session.createCriteria(Product.class); |
|
criteria.add(Expression.eq("category", category)); |
|
criteria.setMaxResults(6); |
|
return criteria.list(); |
|
} |
|
}; |
|
} |
|
}</programlisting> |
|
|
|
<para>A callback implementation effectively can be used for any |
|
Hibernate data access. <classname>HibernateTemplate</classname> will |
|
ensure that <interfacename>Session</interfacename> instances are |
|
properly opened and closed, and automatically participate in |
|
transactions. The template instances are thread-safe and reusable, |
|
they can thus be kept as instance variables of the surrounding class. |
|
For simple single step actions like a single find, load, saveOrUpdate, |
|
or delete call, <classname>HibernateTemplate</classname> offers |
|
alternative convenience methods that can replace such one line |
|
callback implementations. Furthermore, Spring provides a convenient |
|
<classname>HibernateDaoSupport</classname> base class that provides a |
|
<methodname>setSessionFactory(..)</methodname> method for receiving a |
|
<interfacename>SessionFactory</interfacename>, and |
|
<methodname>getSessionFactory()</methodname> and |
|
<methodname>getHibernateTemplate()</methodname>for use by subclasses. |
|
In combination, this allows for very simple DAO implementations for |
|
typical requirements:</para> |
|
|
|
<programlisting language="java">public class ProductDaoImpl extends HibernateDaoSupport implements ProductDao { |
|
|
|
public Collection loadProductsByCategory(String category) throws DataAccessException { |
|
return this.getHibernateTemplate().find( |
|
"from test.Product product where product.category=?", category); |
|
} |
|
}</programlisting> |
|
</section> |
|
|
|
<section id="orm-hibernate-daos"> |
|
<title>Implementing Spring-based DAOs without callbacks</title> |
|
|
|
<para>As alternative to using Spring's |
|
<classname>HibernateTemplate</classname> to implement DAOs, data |
|
access code can also be written in a more traditional fashion, without |
|
wrapping the Hibernate access code in a callback, while still |
|
respecting and participating in Spring's generic |
|
<classname>DataAccessException</classname> hierarchy. The |
|
<classname>HibernateDaoSupport</classname> base class offers methods |
|
to access the current transactional |
|
<interfacename>Session</interfacename> and to convert exceptions in |
|
such a scenario; similar methods are also available as static helpers |
|
on the <classname>SessionFactoryUtils</classname> class. Note that |
|
such code will usually pass '<literal>false</literal>' as the value of |
|
the <methodname>getSession(..)</methodname> methods |
|
'<literal>allowCreate</literal>' argument, to enforce running within a |
|
transaction (which avoids the need to close the returned |
|
<interfacename>Session</interfacename>, as its lifecycle is managed by |
|
the transaction).</para> |
|
|
|
<programlisting language="java">public class HibernateProductDao extends HibernateDaoSupport implements ProductDao { |
|
|
|
public Collection loadProductsByCategory(String category) throws DataAccessException, MyException { |
|
Session session = getSession(false); |
|
try { |
|
Query query = session.createQuery("from test.Product product where product.category=?"); |
|
query.setString(0, category); |
|
List result = query.list(); |
|
if (result == null) { |
|
throw new MyException("No search results."); |
|
} |
|
return result; |
|
} |
|
catch (HibernateException ex) { |
|
throw convertHibernateAccessException(ex); |
|
} |
|
} |
|
}</programlisting> |
|
|
|
<para>The advantage of such direct Hibernate access code is that it |
|
allows <emphasis>any</emphasis> checked application exception to be |
|
thrown within the data access code; contrast this to the |
|
<classname>HibernateTemplate</classname> class which is restricted to |
|
throwing only unchecked exceptions within the callback. Note that you |
|
can often defer the corresponding checks and the throwing of |
|
application exceptions to after the callback, which still allows |
|
working with <classname>HibernateTemplate</classname>. In general, the |
|
<classname>HibernateTemplate</classname> class' convenience methods |
|
are simpler and more convenient for many scenarios.</para> |
|
</section> |
|
</section> |
|
|
|
<section id="classic-spring-jdo"> |
|
<title>JDO</title> |
|
|
|
<para>For the currently recommended usage patterns for JDO see <xref |
|
linkend="orm-jdo" /></para> |
|
|
|
<section id="orm-jdo-template"> |
|
<title><classname>JdoTemplate</classname> and |
|
<classname>JdoDaoSupport</classname></title> |
|
|
|
<para>Each JDO-based DAO will then receive the |
|
<interfacename>PersistenceManagerFactory</interfacename> through |
|
dependency injection. Such a DAO could be coded against plain JDO API, |
|
working with the given |
|
<interfacename>PersistenceManagerFactory</interfacename>, but will |
|
usually rather be used with the Spring Framework's |
|
<classname>JdoTemplate</classname>:</para> |
|
|
|
<programlisting language="xml"><beans> |
|
|
|
<bean id="myProductDao" class="product.ProductDaoImpl"> |
|
<property name="persistenceManagerFactory" ref="myPmf"/> |
|
</bean> |
|
|
|
</beans></programlisting> |
|
|
|
<programlisting language="java">public class ProductDaoImpl implements ProductDao { |
|
|
|
private JdoTemplate jdoTemplate; |
|
|
|
public void setPersistenceManagerFactory(PersistenceManagerFactory pmf) { |
|
this.jdoTemplate = new JdoTemplate(pmf); |
|
} |
|
|
|
public Collection loadProductsByCategory(final String category) throws DataAccessException { |
|
return (Collection) this.jdoTemplate.execute(new JdoCallback() { |
|
public Object doInJdo(PersistenceManager pm) throws JDOException { |
|
Query query = pm.newQuery(Product.class, "category = pCategory"); |
|
query.declareParameters("String pCategory"); |
|
List result = query.execute(category); |
|
<lineannotation>// do some further stuff with the result list</lineannotation> |
|
return result; |
|
} |
|
}); |
|
} |
|
}</programlisting> |
|
|
|
<para>A callback implementation can effectively be used for any JDO |
|
data access. <classname>JdoTemplate</classname> will ensure that |
|
<classname>PersistenceManager</classname>s are properly opened and |
|
closed, and automatically participate in transactions. The template |
|
instances are thread-safe and reusable, they can thus be kept as |
|
instance variables of the surrounding class. For simple single-step |
|
actions such as a single <literal>find</literal>, |
|
<literal>load</literal>, <literal>makePersistent</literal>, or |
|
<literal>delete</literal> call, <classname>JdoTemplate</classname> |
|
offers alternative convenience methods that can replace such one line |
|
callback implementations. Furthermore, Spring provides a convenient |
|
<classname>JdoDaoSupport</classname> base class that provides a |
|
<literal>setPersistenceManagerFactory(..)</literal> method for |
|
receiving a <classname>PersistenceManagerFactory</classname>, and |
|
<methodname>getPersistenceManagerFactory()</methodname> and |
|
<methodname>getJdoTemplate()</methodname> for use by subclasses. In |
|
combination, this allows for very simple DAO implementations for |
|
typical requirements:</para> |
|
|
|
<programlisting language="java">public class ProductDaoImpl extends JdoDaoSupport implements ProductDao { |
|
|
|
public Collection loadProductsByCategory(String category) throws DataAccessException { |
|
return getJdoTemplate().find( |
|
Product.class, "category = pCategory", "String category", new Object[] {category}); |
|
} |
|
}</programlisting> |
|
|
|
<para>As alternative to working with Spring's |
|
<classname>JdoTemplate</classname>, you can also code Spring-based |
|
DAOs at the JDO API level, explicitly opening and closing a |
|
<interfacename>PersistenceManager</interfacename>. As elaborated in |
|
the corresponding Hibernate section, the main advantage of this |
|
approach is that your data access code is able to throw checked |
|
exceptions. <classname>JdoDaoSupport</classname> offers a variety of |
|
support methods for this scenario, for fetching and releasing a |
|
transactional <interfacename>PersistenceManager</interfacename> as |
|
well as for converting exceptions.</para> |
|
</section> |
|
</section> |
|
|
|
<section id="classic-spring-jpa"> |
|
<title>JPA</title> |
|
|
|
<para>For the currently recommended usage patterns for JPA see <xref |
|
linkend="orm-jpa" /></para> |
|
|
|
<section id="orm-jpa-template"> |
|
<title><classname>JpaTemplate</classname> and |
|
<classname>JpaDaoSupport</classname></title> |
|
|
|
<para>Each JPA-based DAO will then receive a |
|
<interfacename>EntityManagerFactory</interfacename> via dependency |
|
injection. Such a DAO can be coded against plain JPA and work with the |
|
given <interfacename>EntityManagerFactory</interfacename> or through |
|
Spring's <classname>JpaTemplate</classname>:</para> |
|
|
|
<programlisting language="xml"><beans> |
|
|
|
<bean id="myProductDao" class="product.ProductDaoImpl"> |
|
<property name="entityManagerFactory" ref="myEmf"/> |
|
</bean> |
|
|
|
</beans></programlisting> |
|
|
|
<programlisting language="java">public class JpaProductDao implements ProductDao { |
|
|
|
private JpaTemplate jpaTemplate; |
|
|
|
public void setEntityManagerFactory(EntityManagerFactory emf) { |
|
this.jpaTemplate = new JpaTemplate(emf); |
|
} |
|
|
|
public Collection loadProductsByCategory(final String category) throws DataAccessException { |
|
return (Collection) this.jpaTemplate.execute(new JpaCallback() { |
|
public Object doInJpa(EntityManager em) throws PersistenceException { |
|
Query query = em.createQuery("from Product as p where p.category = :category"); |
|
query.setParameter("category", category); |
|
List result = query.getResultList(); |
|
<lineannotation>// do some further processing with the result list</lineannotation> |
|
return result; |
|
} |
|
}); |
|
} |
|
}</programlisting> |
|
|
|
<para>The <interfacename>JpaCallback</interfacename> implementation |
|
allows any type of JPA data access. The |
|
<classname>JpaTemplate</classname> will ensure that |
|
<interfacename>EntityManager</interfacename>s are properly opened and |
|
closed and automatically participate in transactions. Moreover, the |
|
<classname>JpaTemplate</classname> properly handles exceptions, making |
|
sure resources are cleaned up and the appropriate transactions rolled |
|
back. The template instances are thread-safe and reusable and they can |
|
be kept as instance variable of the enclosing class. Note that |
|
<classname>JpaTemplate</classname> offers single-step actions such as |
|
find, load, merge, etc along with alternative convenience methods that |
|
can replace one line callback implementations.</para> |
|
|
|
<para>Furthermore, Spring provides a convenient |
|
<classname>JpaDaoSupport</classname> base class that provides the |
|
<literal>get/setEntityManagerFactory</literal> and |
|
<methodname>getJpaTemplate()</methodname> to be used by |
|
subclasses:</para> |
|
|
|
<programlisting language="java">public class ProductDaoImpl extends JpaDaoSupport implements ProductDao { |
|
|
|
public Collection loadProductsByCategory(String category) throws DataAccessException { |
|
Map<String, String> params = new HashMap<String, String>(); |
|
params.put("category", category); |
|
return getJpaTemplate().findByNamedParams("from Product as p where p.category = :category", params); |
|
} |
|
}</programlisting> |
|
|
|
<para>Besides working with Spring's |
|
<classname>JpaTemplate</classname>, one can also code Spring-based |
|
DAOs against the JPA, doing one's own explicit |
|
<interfacename>EntityManager</interfacename> handling. As also |
|
elaborated in the corresponding Hibernate section, the main advantage |
|
of this approach is that your data access code is able to throw |
|
checked exceptions. <classname>JpaDaoSupport</classname> offers a |
|
variety of support methods for this scenario, for retrieving and |
|
releasing a transaction <interfacename>EntityManager</interfacename>, |
|
as well as for converting exceptions.</para> |
|
|
|
<para><emphasis>JpaTemplate mainly exists as a sibling of JdoTemplate |
|
and HibernateTemplate, offering the same style for people used to |
|
it.</emphasis></para> |
|
</section> |
|
</section> |
|
</section> |
|
|
|
<section id="clasic-spring-mvc"> |
|
<title>Classic Spring MVC</title> |
|
|
|
<para>...</para> |
|
</section> |
|
|
|
<section id="classic-spring-jms"> |
|
<title>JMS Usage</title> |
|
|
|
<para>One of the benefits of Spring's JMS support is to shield the user |
|
from differences between the JMS 1.0.2 and 1.1 APIs. (For a description of |
|
the differences between the two APIs see sidebar on Domain Unification). |
|
Since it is now common to encounter only the JMS 1.1 API the use of |
|
classes that are based on the JMS 1.0.2 API has been deprecated in Spring |
|
3.0. This section describes Spring JMS support for the JMS 1.0.2 |
|
deprecated classes. </para> |
|
|
|
<sidebar> |
|
<title>Domain Unification</title> |
|
|
|
<para>There are two major releases of the JMS specification, 1.0.2 and |
|
1.1.</para> |
|
|
|
<para>JMS 1.0.2 defined two types of messaging domains, point-to-point |
|
(Queues) and publish/subscribe (Topics). The 1.0.2 API reflected these |
|
two messaging domains by providing a parallel class hierarchy for each |
|
domain. As a result, a client application became domain specific in its |
|
use of the JMS API. JMS 1.1 introduced the concept of domain unification |
|
that minimized both the functional differences and client API |
|
differences between the two domains. As an example of a functional |
|
difference that was removed, if you use a JMS 1.1 provider you can |
|
transactionally consume a message from one domain and produce a message |
|
on the other using the same |
|
<interfacename>Session</interfacename>.</para> |
|
|
|
<note> |
|
<para>The JMS 1.1 specification was released in April 2002 and |
|
incorporated as part of J2EE 1.4 in November 2003. As a result, common |
|
J2EE 1.3 application servers which are still in widespread use (such |
|
as BEA WebLogic 8.1 and IBM WebSphere 5.1) are based on JMS |
|
1.0.2.</para> |
|
</note> |
|
</sidebar> |
|
|
|
<section id="classic-spring-jms-template"> |
|
<title>JmsTemplate</title> |
|
|
|
<para>Located in the package |
|
<literal>org.springframework.jms.core</literal> the class |
|
<classname>JmsTemplate102</classname> provides all of the features of |
|
the <classname>JmsTemplate</classname> described the JMS chapter, but is |
|
based on the JMS 1.0.2 API instead of the JMS 1.1 API. As a consequence, |
|
if you are using JmsTemplate102 you need to set the boolean property |
|
<property>pubSubDomain</property> to configure the |
|
<classname>JmsTemplate</classname> with knowledge of what JMS domain is |
|
being used. By default the value of this property is false, indicating |
|
that the point-to-point domain, Queues, will be used.</para> |
|
</section> |
|
|
|
<section id="classic-spring-aysnc-messages"> |
|
<title>Asynchronous Message Reception </title> |
|
|
|
<para><link |
|
linkend="jms-receiving-async-message-listener-adapter">MessageListenerAdapter's</link> |
|
are used in conjunction with Spring's <link linkend="jms-mdp">message |
|
listener containers</link> to support asynchronous message reception by |
|
exposing almost any class as a Message-driven POJO. If you are using the |
|
JMS 1.0.2 API, you will want to use the 1.0.2 specific classes such as |
|
<classname>MessageListenerAdapter102</classname>, |
|
<classname>SimpleMessageListenerContainer102</classname>, and |
|
<classname>DefaultMessageListenerContainer102</classname>. These classes |
|
provide the same functionality as the JMS 1.1 based counterparts but |
|
rely only on the JMS 1.0.2 API. </para> |
|
</section> |
|
|
|
<section id="classic-spring-jms-connections"> |
|
<title>Connections</title> |
|
|
|
<para>The <classname>ConnectionFactory</classname> interface is part of |
|
the JMS specification and serves as the entry point for working with |
|
JMS. Spring provides an implementation of the |
|
<classname>ConnectionFactory</classname> interface, |
|
<classname>SingleConnectionFactory102</classname>, based on the JMS |
|
1.0.2 API that will return the same <classname>Connection</classname> on |
|
all <methodname>createConnection()</methodname> calls and ignore calls to |
|
<methodname>close()</methodname>. You will need to set the boolean |
|
property <property>pubSubDomain</property> to indicate which messaging |
|
domain is used as <classname>SingleConnectionFactory102</classname> will |
|
always explicitly differentiate between a |
|
<classname>javax.jms.QueueConnection</classname> and a |
|
<classname>javax.jmsTopicConnection</classname>.</para> |
|
</section> |
|
|
|
<section id="classic-spring-jms-tx-management"> |
|
<title>Transaction Management</title> |
|
|
|
<para>In a JMS 1.0.2 environment the class |
|
<classname>JmsTransactionManager102</classname> provides support for |
|
managing JMS transactions for a single Connection Factory. Please refer |
|
to the reference documentation on <link linkend="jms-tx">JMS Transaction |
|
Management</link> for more information on this functionality.</para> |
|
</section> |
|
</section> |
|
</appendix>
|
|
|