Spring Framework Best Practices

antlertextureΛογισμικό & κατασκευή λογ/κού

14 Ιουλ 2012 (πριν από 5 χρόνια και 1 μήνα)

418 εμφανίσεις

16
th
July 2007
Better architecture by design
JAVAWUG BOF 27, Skills Matter, London
*PP* ©
2007
Peter Pilgrim
Java EE Software Designer Architect
Independent Contractor
Financial Services
Java Champion
http://jroller.com/page/peter_pilgrim

http://jroller.com/page/javawug

Spring Framework Best
Practices
2
Talk Outline
Spring Framework Primary School Class
Spring Version 1.x
Spring Version
2.0
Spring Version
2.1
and JSR
316
Spring Hints & Tips
Summary
3
What is Spring?
Managed Dependency Injection Framework
Life-cycle of POJOS
Dependency Injection for JavaBeans & Interfaces
Plethora of Utility APIs and idioms
4
What is Spring Version 1?
Core Spring
Dynamic
AOP
Data
Access
Declarative
TX
Mail
Remoting
MVC
Bean Factory
Container
Scheduling
Simplifying J2EE Development
5
What is Spring Version 2?
Core Spring
Dynamic
AOP
Data
Access
Declarative
TX
Mail
Remoting
Servlet MVC
Bean Factory
Container
Scheduling
Simplifying J(2)EE Development
Annotations (TX)
AspectJ
Libraries
Task
Executor
XML Namespaces
Tag Libs
Java 5
Portlet MVC
Scripting Languages
6
What is expected in Spring Version 2.1?
Core Spring
Dynamic
AOP
Alternative Data
Access
Declarative
TX
Mail
Remoting
Servlet
MVC
Bean Factory
Container
Scheduling
Simplifying Java EE Development
AspectJ
Integration
Task
Executor
Extra XML
Namespaces
Tag Libs
Java EE 5
Portlet MVC
Annotation Driven Injection
OSGi Modules
Annotation TX
Annotation Componentisation
Familiar Data
Access
Spring Security
7
Goals of Spring 2.0
Backwards compatible
Annotation Driven Transactions
Simplified Java 5 Support
XML Namespace extension for ease-of-configuration
Improved JMS Messaging, local and XA transactions
Task Executor
AspectJ library support
JPA Integration
Portlet MVC
8
Goals of Spring 2.1
OSGi is the biggest value add
Module JARS
Special OSGi XML namespace
Annotation Driven Injection
Spring Back-ends (JCA and LDAP support)
Enhanced JPA support
9
Goals of Spring 2.1
OSGi is the biggest value add
Module JARS
Special OSGi XML namespace
Annotation Driven Injection
Spring Back-ends (JCA and LDAP support)
Enhanced JPA support
10
Future of Spring Development Java EE JSR 316
Eventually we will be locked into Spring, but not yet!!!
Spring OSGi does obscure the raw APIs
Java EE 6 has a new JSR 316
Java EE may incorporate Spring's ideas
Modularisation of Java EE (JSR 277 and 294)
JSR 277 Java Module System
JSR 294 Improved Modularity Support
OSGi forces future EE architects to research new
“materials” for building software
11
Configuration of Transactions: Manager & Advice
<
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
=
"..."
>

<
tx:advice
id
=
"txAdvice"
transaction-manager
=
"txManager"
>
<
tx:attributes
>
<
tx:method
name
=
"get*"
read-only
=
"true"
/>
<
tx:method
name
=
"find*"
read-only
=
"true"
/>
<
tx:method
name
=
"*"
/>
</
tx:attributes
>

</
tx:advice
>

<
bean
id
=
"
txManager
"

class
=
"org.springframework.orm.hibernate3.
HibernateTransactionManager"
>
<
property
name
=
"sessionFactory"
ref
=
"sessionFactory"
/>

</
bean
>

</
beans
>
12
Configuration of Transactions: Pointcuts
<
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
=
"..."
>

<aop:config>
<aop:pointcut id="
projectServiceOperation
"
expression="
execution(* websitetracker.service.*.*(..))
" />
<aop:advisor advice-ref="
txAdvice
"
pointcut-ref="
projectServiceOperation
" />

</aop:config>

<aop:config>...</aop:config>
...
</
beans
>
13
Configuration: Hibernate Session Factory
<
beans ...
>

<
bean
id
=
"
sessionFactory
"
class
=
"org.springframework.orm.
hibernate3.LocalSessionFactoryBean"
>

<
property
name
=
"
mappingResources
"
>

<
list
>

<
value
>
websitetracker/domain/IpAddressReverse.hbm.xml
</
value
>

<
value
>
websitetracker/domain/Website.hbm.xml
</
value
>

</
list
></
property
>

<
property
name
=
"
hibernateProperties
"
>

<
props
>

<
prop
key
=
"
hibernate.dialect
"
>
org.hibernate.dialect.MySQLDialect
</
prop
>

<
prop
key
=
"hibernate.show_sql"
>
true
</
prop
>
<
prop
key
=
"hibernate.generate_statistics"
>
false
</
prop
>

</
props
></
property
>

<
property
name
=
"
dataSource
"
><
ref
bean
=
"
dataSource
"
/></
property
>
<
property
name
=
"
eventListeners
"
>

<
map
>
<
entry
key
=
"merge"
>

<
bean
class
=
"org.springframework.orm.hibernate3.support.
IdTransferringMergeEventListener
"
/>
</
entry>
</
map
></
property
>


</
bean
> ...
</
beans
>
14
Configuration: Hibernate DAO & Services
<
beans ...
>

<
bean
id
=
"
hibernateTemplate
"
class
=
"org.springframework.
orm.hibernate3.HibernateTemplate"
>

<
property
name
=
"
sessionFactory
"
>

<
ref
local
=
"
sessionFactory
"
/>

</
property
>

</
bean
>

<
bean
id
=
"ipAddressReverseDao"
class
=
"websitetracker.dao.IpAddressReverseDao"
>

<
property
name
=
"
sessionFactory
"
ref
=
"
sessionFactory
"
/>

</
bean
>

<
bean
id
=
"trackReportService"
class
=
"websitetracker.engine.impl.TrackReportServiceImpl"
>

<
property
name
=
"
hibernateTemplate
"
ref
=
"
hibernateTemplate
"
/>

</
bean
>

...
</
beans
>
15
Multiple Application Contexts
Parent and Child bean factory contexts can help modularise
complexity
ApplicationContexts can retrieve wildcarded configuration
files.
For Spring managed EJBs and MDB prefer to use
ContextSingletonBeanFactoryLocator
public class
StartUpBean
extends
AbstractStatelessSessionBean
{
public boolean start( ... )
setBeanFactoryLocator(

ContextSingletonBeanFactoryLocator

.getInstance(“
classpath:fitrader-context.xml
”));

setBeanFactoryLocatorKey(“
FI-TRADER
”);

return true;
}
16
Define A Master Application Context
<!-- “
fitrader-context.xml”
-->
<
beans ...
>
<!-- defines the entire container context -->
<
bean
id
=
"
FI-TRADER
"
class
=
"
org.springframework.context.
support.ClassPathXmlApplicationContext
"
>
<
constructor-arg
index
=
"0"
>
<
list
>

<!-- service layer -->


<
value
>
fitrader/service/beans-context-service.xml
</
value
>
<!-- dao layer -->


<
value
>
fitrader/dao/beans-context-dao.xml
</
value
>



<!-- Transaction Manager -->

<
value
>
fitrader/dao/tx/beans-context-transaction.xml
</
value
>


<!-- AOP -->

<
value
>
fitrader
/aop/beans-context-aop.xml
</
value
>
</
list
>
</
constructor-arg
>
<
constructor-arg
index
=
"1"
><
value
>
true
</
value
></
constructor-arg
>
</
bean
>
</
beans
>
17
Share Contexts Among Spring Managed EJBs
Standard Spring managed EJB examples from books create
and retrieve application contexts separately
Consumes memory per deployment and EJB instance!
Arrange for Spring managed EJBs to retrieve master
application context instead
Share application context Message Driven Beans especially
with point-to-point queue
18
Spring Managed EJB Example
public class
TradeRouteProcessorRemoteEJB

extends
AbstractStatelessSessionBean
implements ITradeRouteProcessor
{

private static final String BEAN_NAME = "
tradeRouteProcessor
";

private ITradeRouteProcessorScheduler
delegate
;


public TradeRouteProcessorRemoteEJB() {

super();

setBeanFactoryLocator(

ContextSingletonBeanFactoryLocator

.getInstance(“
classpath:fitrader-context.xml
”));

setBeanFactoryLocatorKey(“
FI-TRADER
”);

}


protected void onEjbCreate() throws CreateException {

delegate
= (ITradeRouteProcessor)
getBeanFactory().getBean( BEAN_NAME);

}

...
}
19
Test Driven Development
Write to Java interfaces or refactor them out
Consider
EasyMock
for functional testing
AbstractSpringDatabaseTestCase

is a great
class to extend for an application database unit test
Tactile techniques can help insert dummy data for test
purposes. (
JdbcTemplate
)
20
Easy Mock Advice
Consider a base test class for functional testing
Pull up useful DAO & Service classes in the base class
Refactor common ground in concrete classes
Write creational methods on the base classes
Call EasyMock.verify() !!!
21
Maven 2.0 Spring Framework Java EE Setup
Eclipse IDE with Maven 2.0, Spring & Hibernate
issues (prefer parallel project structure)
Configure a general application context
Please store under
src\main\resources
!
Configure at least one test application context
Please store under
src\test\resources
!
Organise multiple file support for large applications
Install into local repository frequently!
Select all projects and hit
F5
!! (Grab a Biscuit and tea)
Prefer Profiles to filtered resources! Eclipse tramples.
22
A Generic DAO
Java 5 makes strong-typed collections easier
We can write a generic DAO
We can use the auto-complete feature in our IDEs
We are less likely to make errors in RTTI / casting!
Extendible to named queries and criterion
23
Generic DAO Interface
public

interface

IPersistenceDao
<E, PK
extends
Serializable> {

public

abstract

void
saveOrUpdate(E transientInstance);

public

abstract

void
attachDirty(E instance);

public

abstract

void
attachClean(E instance);

public

abstract

void
delete(E persistentInstance);

public

abstract
E merge(E detachedInstance);

public

abstract
E findById(
PK
id);

public

abstract
List<E> findByExample(E instance);
}
24
Abstract Persistence DAO
public

abstract

class
AbstractPersistenceDao<E, PK
extends
Serializable>
extends
HibernateDaoSupport

implements
IPersistenceDao<E, PK> {

private
Class<E>
type
;

public
AbstractPersistenceDao( Class<E> type ) {

super
();
this
.
type
= type;
}

public

void
saveOrUpdate(E transientInstance) {

getHibernateTemplate().saveOrUpdate(transientInstance);

}

public
E findById(PK id) {

logger
.debug(
"getting "
+
type
.getName()+
" instance with id: "
+ id);

return (E) getHibernateTemplate().get( packageClassName, id);

}
...
}
25
Concrete Generic DAO
public

class
IpAddressReverseDao
extends

AbstractPersistenceDao<IpAddressReverse,Integer> {

public
IpAddressReverseDao() {

super
( IpAddressReverse.
class
);

}


@SuppressWarnings
(
"unchecked"
)

public
List<IpAddressReverse> getAll() {

return
getHibernateTemplate().find(
"select i from IpAddressReverse as i"
);

}

...
}
26
Executive Summary
Review of Spring Framework 2.0 / 2.1
Discussion about the future of this framework
Competing frameworks such as Google Guice
Relevance to modularisation and architectural assembly
Sharing application contexts
Testing
Generic DAO
27
Time for Questions?
Q & A
28
Illustration