spring in action craig walls [email protected] blog: wiki:

57
Spring in Action Craig Walls [email protected] Blog: http://www.springinaction.com Wiki: http://wiki.habuma.com

Upload: silvester-dean

Post on 13-Jan-2016

221 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

Spring in Action

Craig Walls

[email protected]

Blog: http://www.springinaction.com

Wiki: http://wiki.habuma.com

Page 2: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

About you…

• Java? .NET? Ruby/Rails?– Java 6? Java 5? Java 1.4? Java 1.3? 1.2

or older?

• Who’s using Spring? How long?– Spring 1.2? Spring 2? Spring 2.1?

• Favorite session so far?

• What brings you to this session?

Page 3: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

About me

• Agile developer with Semantra– Natural language business intelligence

• Developing software professionally for over 13 years– Telecom, Finance, Retail, Education– Java for most of that– Also some C/C++, C#/.NET, Ruby

• Spring fanatic

Page 4: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

Who this presentation is for

• Spring newbies– Crash course in all things Spring

• Spring experts– Lots of familiar material– Maybe something you don’t know– Some insight into what’s new and coming

up in the next versions of Spring

Page 5: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

What is Spring?

Page 6: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

Spring is…

• A POJO container?

• A lightweight framework?

• A platform?

• A catalyst for change?

Page 7: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

JCA

Spring does…

DependencyInjection

AOP

JDBCJDO

JPAHibernate iBATIS

TransactionsSecurity

Caching

RMIHessian

Burlap

HttpInvokerSOAP

JMSJMX

E-mail JNDI

Scheduling

EJB

Web MVC

PortletMVC

Web Flow

Rich Client

Struts

Struts 2/WebWork 2

TapestryJSF

AJAX

Spring-WS

OSGiSpring Batch

.NET

XML

JavaConfig

Ruby

Groovy

SpringIDE

Page 8: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

Spring does…

DependencyInjection

AOP

Page 9: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

Dependency Injection

Page 10: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

DI in a nutshell

• Without DI, objects get their own dependencies– Directly through construction– Through factories

• With DI, objects are given their dependencies– Through constructors– Through setter methods– Indirectly through method replacement

• DI + interfaces = loosely coupled objects

Page 11: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

Knights and Quests

• Imagine a ValiantKnight that embarks on quests

• A ValiantKnight needs a Quest

• Quest is an interface:public interface Quest { void embark();}

Page 12: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

What’s wrong with this?

public class ValiantKnight { public void embarkOnQuest() { Quest quest = new SlayDragonQuest(); quest.embark(); }}

Page 13: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

How about this?

public class ValiantKnight{ public void embarkOnQuest() { Quest quest = QuestFactory. getInstance().getQuest(); quest.embark(); }}

Page 14: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

Is this any better?

public class ValiantKnight { public void embarkOnQuest() { InitialContext ctx = null; try { ctx = new InitialContext(); Quest quest = (Quest) ctx.lookup( "java:comp/env/Quest"); quest.embark(); } catch (NamingException e) { } finally { if(ctx != null) { try {ctx.close(); } catch (Exception e) {} } } }}

Page 15: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

Let’s try this…

public class ValiantKnight { private Quest quest;

public ValiantKnight(Quest quest) { this.quest = quest; }

public void embarkOnQuest() { quest.embark(); }}

Page 16: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

Or perhaps…

public class ValiantKnight { private Quest quest;

public ValiantKnight() {}

public void setQuest(Quest quest) { this.quest = quest; }

public void embarkOnQuest() { quest.embark(); }}

Where does Questcome from?

How is itImplemented?

Page 17: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

Wiring in Spring (constructor)

<bean id="knight" class="com.springinaction.ValiantKnight"> <constructor-arg ref="quest" /></bean>

<bean id="quest" class="com.springinaction.SlayDragonQuest" />

Page 18: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

Wiring in Spring (setter)

<bean id="knight" class="com.springinaction.ValiantKnight"> <property name="quest" ref="quest" /></bean>

<bean id="quest" class="com.springinaction.SlayDragonQuest" />

Page 19: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

Wiring in Spring 2.5 (annotations)

@Componentpublic class ValiantKnight {

@Autowired private Quest quest;

public ValiantKnight() {}

public void embarkOnQuest() { quest.embark(); }}

Page 20: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

Aspect-Oriented Programming

Page 21: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

AOP in a nutshell

• Aspects decouple “concerns” from the objects that they apply to

• Common examples: Logging, caching, security, transactions

• Imagine a Minstrel class that chronicles a Knight’s exploits in song…

Page 22: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

Without AOP

public void embarkOnQuest() { minstrel.sing( "Fa la la, the knight is so brave!"); quest.embark(); minstrel.sing( "He did embark on a noble quest!");}

Is this really the knight’s job?

Page 23: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

With AOP

public void embarkOnQuest() { quest.embark();}

Where’s the Minstrel?

Page 24: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

Minstrel.java

public class Minstrel { public void singBefore() { System.out.println( "Fa la la, the knight is so brave!"); }

public void singAfter() { System.out.println( "He did embark on a noble quest!"); }}

Page 25: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

Weaving aspects in Spring

<bean id="minstrel" class="com.springinaction.Minstrel" />

<aop:config> <aop:aspect ref="minstrel"> <aop:pointcut id="embarkment" expression="execution(* *.embarkOnQuest(..))" /> <aop:before method="singBefore" pointcut-ref="embarkment" /> <aop:after-returning method="singAfter" pointcut-ref="embarkment" /> </aop:aspect></aop:config>

Page 26: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

Using @AspectJ

@Aspectpublic class Minstrel { @Pointcut("execution(* *.embarkOnQuest(..))") public void embarkment() {}

@Before("embarkment()") public void singBefore() { System.out.println( "Fa la la, the knight is so brave!"); }

@After("embarkment()") public void singAfter() { System.out.println( "He did embark on a noble quest!"); }}

Page 27: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

In Spring XML…

<aop:aspectj-autoproxy />

Yep…that’s it

Page 28: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

DI meets AOP

• @Configurable enables injection into objects not managed by Spring– Domain objects, for example

• Configure in Spring XML:– Spring 2.0: <aop:spring-configured/>

– Spring 2.1: <context:spring-configured/>

• Needs a load-time-weaver:– Spring 2.0: -javaagent:/path/to/aspect-weaver.jar– Spring 2.1…two options:

• -javaagent:/path/to/spring-agent.jar• <context:load-time-weaver />

Page 29: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

Spring and JDBC

Page 30: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

Conventional JDBCConnection conn = null;PreparedStatement stmt = null;ResultSet rs = null;try { conn = dataSource.getConnection(); stmt = conn.prepareStatement(”select id, first_name, last_name from Employee where id=?"); stmt.setInt(1, id); rs.stmt.executeQuery(); Employee employee = null; if(rs.next()) { employee = new Employee(); employee.setId(rs.getInt(1)); employee.setFirstName(rs.getString(2)); employee.setLastName(rs.getString(3)); } return employee;} catch (SQLException e) {

} finally { try { if(rs ! null) { rs.close(); } if(stmt != null) { stmt.close(); } if(conn != null) { conn.close(); } } catch (SQLException e) {}}

Déjà vu?

What do you intendto do about this???

Page 31: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

SQLException

• The case of the ambiguous and useless checked exception…– SQLException means that something went

wrong with the database…but what?– The types of problems that SQLException

represent are usually not runtime-addressable.

• What can you do in a catch block to handle a column not found error?

Page 32: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

Spring’s DataAccessException

• CannotAcquireLockException• CannotSerializeTransactionException• CleanupFailureDataAccessException• ConcurrencyFailureException• DataAccessException• DataAccessResourceFailureException• DataIntegrityViolationException• DataRetrievalFailureException• DeadlockLoserDataAccesException

• EmptyResultDataAccessException• IncorrectResultSizeDataAccessException• IncorrectUpdateSemanticsDataAccessException• InvalidDataAccessApiUsageException• InvalidDataAccessResourceUsageException• OptimisticLockingFailureException• PermissionDeniedDataAccessException• PessimisticLockingFailureException• TypeMismatchDataAccessException• UncategorizedDataAccessException

Page 33: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

JDBC: Spring-styleList matches = jdbcTemplate.query( "select id, first_name, last_name from Employee" + " where id=?", new Object[] {Long.valueOf(id)}, new RowMapper() { public Object mapRow(ResultSet rs, int rowNum) throws SQLException, DataAccessException { Employee employee = new Employee(); employee.setId(rs.getInt(1)); employee.setFirstName(rs.getString(2)); employee.setLastName(rs.getString(3)); return employee; } });

return matches.size() > 0 ? (Employee) matches.get(0) : null;

Notice no awkwardtry/catch block

And no JDBCboilerplate

Page 34: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

JDBC Template<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" > <property name="driverClassName” value="org.hsqldb.jdbcDriver" /> <property name="url" value="jdbc:hsqldb:hsql://localhost/employee/employee" /> <property name="username" value="sa" /> <property name="password" value="" /></bean>

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" > <property name="dataSource" ref="dataSource" /></bean>

<bean id="employeeDao" class="com.springinaction.JdbcEmployeeDao"> <property name="jdbcTemplate" ref="jdbcTemplate" /></bean>

Page 35: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

JDBC: Spring 2 and Java 5

List<Employee> matches = simpleJdbcTemplate.query( "select id, first_name, last_name from Employee" + " where id=?", new ParameterizedRowMapper<Employee>() { public Employee mapRow(ResultSet rs, int rowNum) throws SQLException { Employee employee = new Employee(); employee.setId(rs.getInt(1)); employee.setFirstName(rs.getString(2)); employee.setLastName(rs.getString(3)); return employee; } }, id);

return matches.size() > 0 ? matches.get(0) : null;

Uses generics

No need to wrapparameters

No need tocast result

Page 36: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

One more thing on templates

• JDBC isn’t the only place where Spring provides templates…– Hibernate– JPA– JDO– TopLink– iBATIS– JCA– JMS– JNDI

Page 37: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

Declarative Transactions

Page 38: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

EJB’s killer feature…

• …now available in convenient POJO form.

• Spring uses AOP to enable declarative transactions on POJO methods– In some ways, even more capable than

EJB transactions (more propagation options, isolation levels…)

Page 39: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

Spring 2 declarative tx

<tx:advice id="txAdvice"> <tx:attributes> <tx:method name="add*" propagation="REQUIRED" /> <tx:method name="*" propagation="SUPPORTS" read-only="true"/> </tx:attributes></tx:advice>

<aop:config> <aop:advisor advice-ref="txAdvice" pointcut="execution(* *..EmployeeService.*(..))" /></aop:config>

Page 40: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

Spring 2 + Java 5 transactions

In service class:

@Transactional(propagation=Propagation.SUPPORTS, readOnly=true)public class EmployeeServiceImpl implements EmployeeService {… @Transactional(propagation=Propagation.REQUIRED,

readOnly=false) public void addEmployee(Employee rant) { … }…}

In Spring XML:

<tx:annotation-driven />

Page 41: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

Spring MVC

Page 42: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

Why Spring MVC?

• Spring usually doesn’t reinvent the wheel…– No persistence framework

• At one time, Struts was only option– And not necessarily a good option

• Spring MVC reinvented the MVC wheel…addressing the shortcomings of Struts

Page 43: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

Struts 1.x Action

public class DisplayCustomerAction extends Action { public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {

CustomerDetailForm cdf = (CustomerDetailForm) form; Customer customer = lookupCustomer(cdf.getAccountNumber()); request.setAttribute("customer", customer);

return mapping.findForward("customerDetail"); }}

Page 44: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

Spring MVC Controller

public class DisplayCustomerController extends AbstractController {

protected ModelAndView handleRequestInternal( HttpServletRequest req, HttpServletResponse response) throws Exception {

long customerId = Long.valueOf(req.getParameter("id")); Customer customer = lookupCustomer(customerId); return new ModelAndView( "customerDetail", customer); }}

Page 45: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

Mapping URLs to controllers

• SimpleUrlHandlerMapping:<bean id="urlMapping" class="org.springframework.web.servlet.handler. SimpleUrlHandlerMapping"> <property name="mappings"> <value> /home.htm=homeController /login.htm=loginController /addSpittle.htm=addSpittleController /addSpitter.htm=addSpitterController </value> </property></bean>

Page 46: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

Auto-mapping of controllers

• ControllerClassNameHandlerMapping:

<bean id="urlMapping" class="org.springframework.web.servlet.mvc.support. ControllerClassNameHandlerMapping" />

– /home.htm HomeController– /login.htm LoginController– /addspittle.htm AddSpittleController

Page 47: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

Mapping view names to views

• InternalResourceViewResolver:<bean id="jspViewResolver" class="org.springframework.web.servlet.view. InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/" /> <property name="suffix" value=".jsp" /></bean>

– “home” /WEB-INF/jsp/home.jsp– “login” /WEB-INF/jsp/login.jsp– “orderForm” /WEB-INF/jsp/orderForm.jsp

Page 48: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

The Struts 1.x Action selection

Page 49: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

Spring Controller Selection

Page 50: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

Spring 2.5 Controllers

• Annotated with @Controller– So that <context:component-scan> can find and register them

• Also annotated with @RequestMapping– To map requests to handler methods

• Optionally annotated with @SessionAttributes– Transparently stores model attributes in session

• Parameters can be mapped with @RequestParam– To automatically map request parameters to handler method

parameters.

• Parameters can also be mapped with @ModelAttribute– Maps a model attribute to a method parameter

• @ModelAttribute can also be applied to methods– To populate the model with the output from the method

Page 51: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

Minimal XML needed for MVC

<context:component-scan

base-package="com.habuma.spitter.mvc" />

<bean

class="org.springframework.web.servlet.

mvc.annotation.

AnnotationMethodHandlerAdapter" />

Auto-register all classes incom.habuma.spitter.mvc package

Map all @RequestMapping-annotated beans

Page 52: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

Annotated controller example@Controller

@RequestMapping("/editPet.do")

@SessionAttributes("pet")

public class EditPetForm {

@ModelAttribute("types")

public Collection<PetType> populatePetTypes() { return this.clinic.getPetTypes(); }

@RequestMapping(type = "POST")

public String processSubmit(@ModelAttribute("pet") Pet pet, BindingResult result, SessionStatus status) {

new PetValidator().validate(pet, result);

if (result.hasErrors()) { return "petForm"; }

else {

this.clinic.storePet(pet);

status.setComplete();

return "redirect:owner.do?ownerId=" + pet.getOwner().getId();

}

}

}

Page 53: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

Annotated controller (2)

@Controller

@RequestMapping("/editPet.do")

@SessionAttributes("pet")

public class EditPetForm {

@RequestMapping(type = "GET")

public String setupForm(

@RequestParam("petId") int petId, ModelMap model) {

Pet pet = this.clinic.loadPet(petId);

model.addAttribute("pet", pet);

return "petForm";

}

}

Page 54: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

What about…???

• Struts 2/WebWork 2?

• JSF?

• Tapestry?

• Wicket?

• Seam?

• Grails?

• The billions of other MVC frameworks

Page 55: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

What’s new in Spring 2

• New/extensible configuration namespaces• Easier AOP and support for @AspectJ• Easier transactions• Injection into objects not managed by Spring• Support for JPA• Asynchronous JMS support• New JDBC templates (Java 5 and named parameters)• New form-binding JSP tag library• Portlet MVC• Dynamic language beans (JRuby, Groovy, BeanShell)• JMX: Notifications and registration control• Convention over configuration improvements

Page 56: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

What’s coming in Spring 2.5

• JMS configuration namespace• Context configuration namespace

– <aop:spring-configured> moves to <context:spring-configured>

• Annotation-driven configuration– @Component, @Autowired– JSR-250: @Resource, @PostConstructor, @PreDestroy– @Controller, @RequestMapping, @SessionAttributes, @ModelAttribute,

@RequestParam

• Autodetected components• Requires JDK 1.4 or higher• Named parameters added to SimpleJdbcTemplate• ParameterizedBeanPropertyRowMapper for automatically mapping

between columns and bean properties• <context:load-time-weaver/> : Spring configured load time weaving• Hibernate 2.1 support goes away• JUnit 4.x support (SpringJUnit4ClassRunner)

Page 57: Spring in Action Craig Walls craig@habuma.com Blog:  Wiki:

Q & ADon’t forget to turn in evals!!!

http://www.springinaction.com

[email protected]