Winter is coming

batterycopperInternet and Web Development

Nov 12, 2013 (3 years and 9 months ago)

112 views

Winter is
coming

(Johannes
vs

Johanes

Nets
DevDay

2012

Johannes
Brodwall
, Principal Architect

Steria

Norway


@
jhannes

Why

dependency

detox
?


<?
xml

version
=
"1.0"
encoding
=
"UTF
-
8"
?>

<
beans

default
-
autowire
=
"
constructor
"
>



<
bean

class
=
"
no.steria.spring.ApplicationServiceImpl
"
/>



<
bean

class
=
"
no.steria.spring.IncrementService
"
/>



<
bean

class
=
"
no.steria.spring.ReportService
"
/>



<
bean

class
=
"
no.steria.winterapp.provided.JdbcEntryDao
"
/>



<
bean

class
=
"
org.springframework.jndi.JndiObjectFactoryBean
"
>


<
property
name
=
"
jndiName
"
value
=
"
jdbc
/
primaryDs
"
/>


</
bean
>

</
beans
>

public

static

void

main(String[]
args
){


ApplicationContext

context

=


new

ClassPathXmlApplicationContext
(
"..."
);


ApplicationService

applicationService

=


context.getBean
(
ApplicationService.
class
);


applicationService.incrementAndReport
(
new

Date());

}

Who created that
object?

Is that setter still
in use?

Are we sure
@Transactional is
picked up?

How does
@
Transaction
work?!

In what <import> is
that bean defined?

Where is the
business logic?!

The “Service” here
does nothing!

Less
magic


public

static

void

main(String[]
args
)
{


ApplicationService

applicationService

=


new

ApplicationService
(
createDataSource
());


applicationService.incrementAndReport
(
new

Date());


}

Explicit

coupling

public

class

ApplicationService

{



private

IncrementService

incrementService
;


private

ReportService

reportService
;



public

ApplicationService
(
DataSource

dataSource
) {


this
(
new

IncrementService
(
dataSource
),
new

ReportService
(
dataSource
));


}



public

ApplicationService
(
IncrementService

incrementSvc
,


ReportService

reportSvc
)
{


this
.
incrementService

=
incrementService
;


this
.
reportService

=
reportService
;


}



public

void

incrementAndReport
(Date date) {


incrementService
.increment
(date);


reportService
.printReport
();


}


}

public

class

IncrementService

{



private

EntryDao

entryDao
;



public

IncrementService
(
DataSource

dataSource
) {


this
(
new

JdbcEntryDao
(
dataSource
));


}



public

IncrementService
(
EntryDao

entryDao
) {


this
.
entryDao

=
entryDao
;


}



public

void

increment
(Date date) {


entryDao
.insertEntry
(
new

Entry
(date));


}


}

Better
quality


Less
searching


Compiler
errors

Ward Cunningham:

”You know you are working
on clean code when each
routine you read

turns out to
be
pretty much what you
expected.


Whence

Spring
framework
?


EJB 2.0


really

sucked


one

feature
:
Transactions
!

Java design in 2003


really

sucked

… Singleton
craze


needed

dependency

control


needed

more
magic

What’s

relevant
today
?


EJB 2.0


um

no
!

Transactions


it’s

really

not
that

hard!

… let
me

show
you

public

interface

TransactionManager

{



Transaction

beginTransaction
();


}


public

interface

Transaction

extends

Closeable

{



void

setCommit
();



void

close
();

}


@Test

public

void

rollbackTransaction
()
throws

Exception {


doThrow
(
new

RuntimeException
()).
when
(
targetObject
).
doIt
();



try

{


transactional
(
targetObject
).
doIt
()
;


fail
(
"
Should

throw

exception
"
);


}
catch

(
RuntimeException

e) {


//
expected


}



verify
(
tx
, never()).
setCommit
();


verify
(
tx
).
close
();

}

protected
<T> T
transactional
(
final

T
targetObject
) {


return

Proxy.
newProxyInstance
(
getClass
().
getClassLoader
(),
…,


new

InvocationHandler
() {


@
Override


public

Object
invoke(…,
Method
method
, Object[]
args
)
{


Transaction

transaction

=
txMgr
.beginTransaction
();


try

{


method.invoke
(
targetObject
,
args
);


transaction.setCommit
();


}
finally

{


transaction.close
();


}


return

null
;


}


});

}

void

inTx
(
ExampleInterface

targetObject
) {


try

(
Transaction

tx

=
txMgr
.beginTransaction
()) {


targetObject.doIt
();


// if
doIt
() throws, we never get
here



//


then close()
rolls back


tx.setCommit
();


}

}

Dependency management


Going

waaaay

over
board

Person
-
Controller

Person
-
Controller
-
Impl

Person
-
Service

Person
-
ServiceImpl

Person
-
Repository

Person
-
Repository

Impl

PersonDao

PersonDao

Impl

Session
-
Factory

Customer

Invoice

Order

Product

How many real
configured things
do we have?

<?
xml

version
=
"1.0"
encoding
=
"UTF
-
8"
?>

<
beans

default
-
autowire
=
"
constructor
"
>



<
bean

class
=
"
no.steria.spring.ApplicationServiceImpl
"
/>



<
bean

class
=
"
no.steria.spring.IncrementService
"
/>



<
bean

class
=
"
no.steria.spring.ReportService
"
/>



<
bean

class
=
"
no.steria.winterapp.provided.JdbcEntryDao
"
/>



<
bean

class
=
"
org.springframework.jndi.JndiObjectFactoryBean
"
>


<
property
name
=
"
jndiName
"
value
=
"
jdbc
/
primaryDs
"
/>


</
bean
>

</
beans
>


DataSource


(Other resources)


Hibernate
SessionFactory


Web Services (URLs)

Varying for tests

public

class

PersonServlet

extends

HttpServlet

{



private

PersonDao

personDao
;



public

void

setPersonDao
(
PersonDao

personDao
) {


this
.
personDao

=
personDao
;


}



@
Override


public

void

init
()
throws

ServletException

{


setPersonDao
(
new

HibernatePersonDao
(
"
jdbc
/
personDs
"
));


}

}


public

class

HibernatePersonDao

implements

PersonDao

{



public

HibernatePersonDao
(
String

jndiDataSource
) {


Configuration

cfg

=
new

Configuration
();


cfg.setProperty
(
Environment.
DATASOURCE
,
jndiDataSource
);



;


cfg.addAnnotatedClass
(
Person.
class
);


this
.
sessionFactory

=
cfg.buildSessionFactory
();


}


public

class

PersonServlet

extends

HttpServlet

{



private

PersonDao

personDao
;



public

void

setPersonDao
(
PersonDao

personDao
) {


this
.
personDao

=
personDao
;


}



@
Override


public

void

init
()
throws

ServletException

{


setPersonDao
(
HibernatePersonDao.getInstance
());


}

}


Jason Gorman

http://codemanship.co.uk/parlezuml/blog/?postid=1097

Announcing A Powerful New
Framework:


Programming
Language

is a powerful new
framework that enables developers to quickly and
easily handle Dependency Injection, Inversion of
Control, Model
-
View
-
Controller and many other
common design problems.


Intermezzo


Which

one

is right?


Messy picture

Well
-
architected
picture

com.app.person

OR

com.app.controller

Now

about

dependency

injection


Don’t inject hard
stuff

Session
-
Factory

PersonController

Service

Repo
sitory

public

class

PersonController

{




private

PersonService

personService
;



@
Autowired


public

PersonController
(
SessionFactory

sf
) {


this
.
personService

=
new

PersonServiceImpl
(
sf
);


}

public

class

PersonServiceImpl

implements



{




private

PersonRepository

personRepo
;



public

PersonServiceImpl
(
SessionFactory

sf
) {


this
.
personRepo

=
new

PersonRepositoryImpl
(
sf
);


}

Hard
stuff

Hard
stuff

public

class

PersonController

{




private

PersonService

personService
;



@
Autowired


public

PersonController
(
SessionFactory

sf
) {


this
.
personService

=
new

PersonServiceImpl
(
sf
);


}




public

PersonControllerImpl
(
PersonService

ps
) {


this
.
personService

=
ps
;


}


For Spring

For
mocking

SPRING!

Session
-
Factory

PersonController

Service

Repo
sitory

InvoiceController

FooServiceImpl

ReportsController

FooController

Service

Repo
sitory

Collapse

service
chains

SPRING!

Session
-
Factory

PersonController

Service

Repo
sitory

InvoiceController

Repository

FooServiceImpl

ReportsController

FooController

Going cold turkey!

Session
-
Factory

PersonServlet

Locator

(singleton O_O)


Injected
” by
servlet

public

class

PersonController

extends

HttpServlet

{




private

PersonService

personService
;




public

PersonController
() {


}




public

PersonController
(
PersonService

personService
) {


this
.
personService

=
personService
;


}




@
Override


public

void

init()
throws

ServletException

{


SessionFactory

sf

=


HibernateLookup.
getInstance
(
getServletContext
());


this
.
personService

=
new

PersonServiceImpl
(
sf
);


}

For
mocking

Look
,
ma
! No
Spring!

Service
Locator

Session
-
Factory

PersonController

Service

Repo
sitory

InvoiceController

Repository

FooServiceImpl

ReportsController

FooController

<<
locator

injection
>>

What

Spring
taught

me

Be
aware

of

dependencies
!

Avoid

differences

between

test and
prod

Stay

the

heck

away

from
frameworks
!

Goal: «
Pretty

much

what

you

expected
»

Takk for meg!

johannes.brodwall@steria.no


http://johannesbrodwall.com

http://sterkblanding.no


http://twitter.com/jhannes