You are on page 1of 35

Lightweight J2EE Architectures

Mihail Chirita, PhD


Consulting Architect
Agile Answers, LLC
mihail.chirita@agileanswers.com
Overview

1.
1.AATale
Taleof
ofTwo
TwoProjects
Projects

2.
2.Classic
ClassicJ2EE
J2EEArchitecture
Architecture

3.
3.Lightweight
Lightweight J2EE
J2EEArchitecture
Architecture

4.
4.Case
CaseStudy
Study

5.
5.Final
FinalRemarks
Remarks
A Tale of Two Projects

• SACWIS – Statewide Automated Child Welfare Information System


• All States must implement it

Minnesota
Florida 
Needs same capabilities as

Started in 1990
Florida

Original cost estimate $32 million 
Similar demographics

Scheduled for delivery in 1998 
Started work in 1999

Development team approx 100 
Finished in 2000

Revised cost estimate $170 million 
Development team of 8

Revised delivery date 2005 
Cost 1.1 million

Source: http://www.martinfowler.com/articles/xp2002.html
Why the difference?

 Minnesota was better at minimizing


requirements

Focusing on the features you need can cut the cost
dramatically

All requirements have a cost – this needs to be clearly
communicated

Build the right application
 Used standard infrastructure - did not
reinvent the wheel!

Build the application right
J2EE - the good

 J2EE is great because it standardizes some


services

Transactions JTA

Remoting

Directory Service JNDI

Pooling

Thread management
J2EE - the bad

 Does not define a programming model


 JNDI and JTA are still low level details
 Often presented as J2EE==EJB
 When using EJB’s is an all or nothing
approach e.g. cannot get transactions
without remoting
J2EE - the ugly

 EJB’s define a programming model



Intrusive API – need to import EJB packages

Code is not reusable

Need to run code inside container

Difficult to test
 Entity EJB

Very limited persistence framework

Makes difficult using basic OOP concepts like
Strategy, Template, Inheritance
Lightweight J2EE

 Wish list

Want to be a able to build J2EE applications and
still use XP practices.

Do not want to stop doing OOP because I am
doing J2EE

Want to be able to run the code anywhere I want

Want the code to be reusable and possibly use
legacy code
Lightweight J2EE (II)

Suggested building blocks



Use a powerful non-intrusive application framework.
 Spring is the best choice I know of.

Use a powerful database access framework like
Toplink, Hibernate or iBatis
 Focus on writing business logic and do not worry about
circumventing limitations in a specific persistence technology
 Use concepts like Strategy, Template, Inheritance
 POJO based domain that can be easily tested outside the
container

Pick a MVC framework of your choice :Struts,
SpringMVC, WebWork if doing web apps
Introducing Spring

 Spring is a non-invasive lightweight application


framework

Provides a consistent structure for an application

Addresses all architectural tiers
 Has three major components

Dependency Injection container

Own AOP framework + allows use of AspectJ,
AspectWerkz for more complex needs

Provides several service abstractions
 DI + AOP + Service Abstractions => powerful and
flexible architecture
Dependency Injection

 Spring includes a powerful IoC container



Wires dependent objects together

Removes the need for Factory, Singleton,
Service Locator

Promotes good OOP practices – e.g. Strategy is
very natural

Enables plugability – switch implementations by
changing configuration files

Enables reuse of legacy code with no or minimal
changes
AOP Support

 Simple and powerful framework that provides


interceptor support and mix-ins
 Need to access the services through a proxy to use
aspects
 Enables delivery of services to POJO
 Promotes an architecture that cleanly separates
cross-cutting concerns from core application logic
 For more complex AOP needs provides hooks for
AspectJ/AspectWerkz
Service Abstractions

 Powerful service abstractions that decouple


the application from specific API
 They are just a library so they can be used
independent of Spring’s IoC
 Hides lots details or repetitive tasks such
resource handling
 High quality, well tested code
 Promotes reusability and testability
Service Abstractions(II)

 Some services provided by Spring



Data abstraction – JDBC, Hibernate, JDO,
TopLink, IBatis

Remoting – RMI, Hessian, Burlap, JAX-RPC

Transactions – can easily switch between local
and JTA transactions

Mail Service, Timer Service, JCA

Web Frameworks – WebWork, Struts, JSF
Hibernate

 Took Java community by storm


 Not new – Toplink and CocoBase provide similar
features
 Powerful and flexible ORM framework

Transparent persistence => focus on modeling the
domain

Provides several inheritance mapping strategies

Two levels of caching

Flexible lazy loading strategies

Integration with open source projects like XDoclet and
Spring
Struts

 De facto standard for web tier development


 Has some limitations but can work around
them
 Lots of books, articles about Struts
 Easier to find Struts developers that with
other Web Frameworks
Case Study

 Client

State agency that needs to build several web based
applications to track budget and expenses for their
projects
 Some requirements:

Each project tracks a large number of expenses

Different building types use different formulas to calculate
fees and progress

Users can modify info only before submitting for approval

Users want to delegate all or part of their responsibilities
to other users

Client’s Project Administrators want to be able to
customize the behavior of the application.
Lightweight vs. Classic J2EE

 Use a rich POJO domain  Use Entity beans


model 
Domain knows about

Domain is responsible with persistence technology and
core business logic and has only runs inside container
no other concerns like
persistence or transactional

Hard to implement basic OOP
behavior concepts like Inheritance

Implements strategies to deal 
Does not allow recurrent calls
with different calculations 
Lots of business logic needs

Can be transferred across the
wire to be in the service Facade
 Use Hibernate to provide 
Cannot transfer over the wire
transparent persistence so need to add DTO layer and

Non-invasive, powerful possibly re-implement some
support for lazy loading, of the calculations
optimistic locking and caching
so performance can be finely
tuned
Lightweight vs. Classic J2EE(II)

 Use Spring’s  Implements a Service Façade


HibernateTemplate to provide 
May be pretty thick because
a DAO layer some of the business logic is

Most methods are one liners pushed in the business layer

No need to be concerned 
Good declarative transactions
about resource management

No transactional concerns at

Get remoting and JAAS
this level security for free but you may
 Provide a Service layer to need it
wrap DAO access 
Cannot add new services

Acts as a façade for several declaratively
DAO interfaces

Here is where you define
transactional behavior and
other cross-cutting concerns

Layer is still pretty thin
because most of the logic is in
the domain
Code example

 Approve expenses functionality



Need to set the project approval state

Need to run some validation checks

Need to create PDF reports and save them in
database

Need to save audit information

Need to send e-mail notification

Need to have transactional behavior
Code example(II)
package gov.osfc.cminvoice.service.spring;
public class CMInvoiceServiceImpl implements ICMInvoiceService {
private ICMInvoiceDAO cmInvoiceDAO;
public void approve(CMInvoice cmInvoice) {
InvoiceTransition transition = invoiceTransitionHelper.getInvoiceTransition(cmInvoice.getApprovalStatus());
cmInvoice.setApprovalStatus(transition.getApproveState());
cmInvoiceDAO.saveCmInvoice(cmInvoice);
}
//setter needed by Spring
public void setCmInvoiceDAO(ICMInvoiceDAO cmInvoiceDAO) {
this.cmInvoiceDAO = cmInvoiceDAO;
}
}

package gov.osfc.cminvoice.service.dao.hibernate;

public class CMInvoiceDAOImpl extends HibernateDaoSupport implements ICMInvoiceDAO{


public void saveCMInvoice(CMInvoice cmInvoice) throws DataAccessException {
getHibernateTemplate().saveOrUpdate(cmInvoice);
}
}
Code example(III)

 Approve method does just one thing –


updates project approval status
 Generating reports, auditing, email,
transactions are aspects that are attached
to the method declaratively
 End result – flexible code focused in doing
one thing at a time and doing it well
 Can plug in and out behavior without
modifying Java code!
Code example(IV)

<beans>
<bean id="cmInvoiceService"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>gov.osfc.cminvoice.service.ICMInvoiceService</value>
</property>
<property name="target">
<ref local="cmInvoiceTarget"/>
</property>
<property name="interceptorNames">
<list> Note: Interceptors order is
<value>validationInterceptor</value> important! E.g. if
<value>transactionInterceptor</value> transaction is configured
<value>reportsAdvisor</value>
after reports, reports are
<value>auditAdvisor</value>
<value>emailNotificationAdvisor</value> not part of the transaction!
</list>
</property>
</bean>
</bean>
Transaction Interceptor

<beans>
<!-- Transaction manager for a single Hibernate SessionFactory (alternative to JTA) -->
<bean id="transactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory"/> • Can specify different Transaction Manager
</property> e.g. can switch to JTA. Change from local
</bean>
to distributed transactions without changing code!
<bean id="transactionInterceptor" • Can use Hibernate + JDBC in same transaction
class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager">
<ref local="transactionManager"/>
</property>
<property name="transactionAttributeSource">
<value>
gov.osfc.cminvoice.service.ICMInvoiceService.*=PROPAGATION_REQUIRED,-java.lang.Exception
</value>
</property>
</bean> • Multiple transactional attributes are supported
</bean> • Allows to specify attribute per method
• Allows to roll back on application exceptions
Spring in the Web Tier
Loading Spring Container
 in web.xml
<web-app>
<!-- Location of the XML files that defines the root application context Applied by
ContextLoaderListener.-->
<display-name>CMInvoice</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext-dataSource.xml,
classpath:/config/applicationContext-cmInvoice.xml
</param-value>
</context-param>
…..
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

</web-app>
Spring in the Web Tier (II)
Struts BaseAction
public abstract class BaseAction extends MappingDispatchAction{

private ICMInvoiceService cmInvoiceService;

protected ICMInvoiceService getCMInvoiceService() {


return cmInvoiceService;
}

public void setServlet(ActionServlet actionServlet) {


super.setServlet(actionServlet);
if (cmInvoiceService == null) {
ServletContext servletContext = actionServlet.getServletContext();
WebApplicationContext wac =
WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
this.cmInvoiceService = (ICMInvoiceService) wac.getBean("cmInvoiceService");
}
}

//other methods like generic exception handler


}
Requirements Revisited

 Each project tracks a large number of expenses


 Different building types use different formulas to
calculate fees and progress
 Users can modify info only before submitting for
approval
 Users want to delegate all or part of their
responsibilities to other users
 Client’s Project Administrators want to be able to
customize the behavior of the application.
Authorization

 The application has security needs that are not meet by


JAAS
 We decided to prevent access to Struts actions
 Naïve approach is to code security checks in each action
 Common complaint is that Struts 1.1 does not support
interceptors – not quite right!
 What I want is to enable declarative authorization in
Struts

Enhance Struts action configuration to take extra parameters

Intercept all Struts action calls
Authorization (II)
<struts-config>
<action-mappings type="gov.osfc.cminvoice.web.action.PermissionActionMapping">
<action path="/review/approveInvoice“ type="gov.osfc.cminvoice.web.action.CMInvoiceAction"
other attributes here! >
<set-property property="permissions" value="invoiceApprove"/>
<forward
name="success"
path=".confirmApproval"/>
</action>
</action-mappings>

<plug-in className="net.sf.struts.saif.SAIFPlugin">
<set-property property="interceptor-config" value="/WEB-INF/interceptor-config.xml"/>
</plug-in>
</struts-config>
Authorization (III)
public class AuthorizationInterceptor implements ActionInterceptor{
public ActionForward doIntercept(InterceptorContext context, ActionInterceptorChain chain) throws Exception {
if (gov.osfc.cminvoice.web.security.AuthorizationHelper.isAuthorized(request)) {
request.setAttribute(WebConstants.REQUEST.CALLER_PERMISSIONS,
AuthorizationHelper.getCallerPermissions(request));
return chain.doIntercept(context);
} else {
AuthorizationHelper.setAuthorizationFailedMessage(request);
ActionMapping mapping = context.getActionMapping();
return mapping.findForward("error");
} Implement doIntercept and proceed
}
if authorized
}

<interceptor-config>
<interceptor name="authorizationInterceptor"
type="gov.osfc.cminvoice.web.action.interceptor.AuthorizationInterceptor"/>
<default-interceptors>
<interceptor name="authorizationInterceptor"/>
</default-interceptors> Configure to intercept all Struts action calls
</interceptor-config>
Requirements Revisited

 Each project tracks a large number of expenses


 Different building types use different formulas to
calculate fees and progress
 Users can modify info only before submitting for
approval
 Users want to delegate all or part of their
responsibilities to other users
 Client’s Project Administrators want to be able to
customize the behavior of the application
Customizable behavior

 Solution

Use a rules engine

Provide client with an interface to define any rule they
like

Provide users with an interface to configure available
rules

Tools used: Drools, Janino and a lot of creativity!
Final Remarks

 Always try to find the simplest solution. If you


cannot explain your problem to a six year old
you did not understand the problem yourself
 Use powerful lightweight frameworks to develop
J2EE applications
 Classic J2EE architecture based on core J2EE
patterns not necessarily the best
 EJB hype may be gone but SOA, WS, BPEL are
just around the corner!
Quote of the day

Any intelligent fool can make things bigger,


more complex, and more violent. It takes a
touch of genius, and a lot of courage, to
move in the opposite direction.
    
Albert Einstein
Resources

 http://www.agileanswers.com/XP2005.ppt
 http://www.springframework.org
 http://www.hibernate.org
 http://struts.apache.org/
 http://www.martinfowler.com/articles/xp2002.html

You might also like