454 lines
21 KiB
XML
454 lines
21 KiB
XML
<?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>
|
|
<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>
|
|
<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>
|
|
<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>
|
|
<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>
|
|
<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>
|