SlideShare una empresa de Scribd logo
1 de 55
EJB applications guided by tests
Jakub Marchwicki
twitter: @kubem
?
twitter: @kubem
The experimentpain
twitter: @kubem
The experiment
nb of slides
pain
twitter: @kubem
The experiment
OK
Severe
health
risk
20 slides
nb of slides
pain
twitter: @kubem
The experiment
OK
Severe
health
risk
60 slides + IDE
nb of slides
pain
twitter: @kubem
It started a year ago
twitter: @kubem
GeeCon 2012 @ Poznań
twitter: @kubem
GeeCon 2012 @ Poznań
twitter: @kubem
But in fact it started much earlier
JBoss 4.x
Taking form 7 to 20 minutes to start
No CI environment
twitter: @kubem
Delivery a feature with
only a single deploy
twitter: @kubem
The Good
Embedded container
Your test is you component
Focused integration testing
twitter: @kubem
INFO - Configuring Service(id=Default Security Service,
type=SecurityService, provider-id=Default Security Service)
INFO - Configuring Service(id=Default Transaction Manager,
type=TransactionManager, provider-id=Default Transaction Manager)
INFO - Creating TransactionManager(id=Default Transaction Manager)
INFO - Creating SecurityService(id=Default Security Service)
INFO - Configuring enterprise application:
/home/kubam/workspaces/java/various/jee-examples/stockapp/stockapp-ejb-
openejbtest/DozerQuotationConverterIntegrationTest
INFO - Auto-deploying ejb DozerConverterCache: EjbDeployment(deployment-
id=DozerConverterCache)
INFO - Auto-deploying ejb DozerQuotationConverter: EjbDeployment(deployment-
id=DozerQuotationConverter)
INFO - Configuring Service(id=Default Managed Container, type=Container,
provider-id=Default ManagedContainer)
INFO - Auto-creating a container for bean
pl.marchwicki.jee.stockapp.ejb.DozerQuotationConverterIntegrationTest:
Container(type=MANAGED, id=Default Managed Container)
INFO - Creating Container(id=Default Managed Container)
INFO - Configuring Service(id=Default Security Service,
type=SecurityService, provider-id=Default Security Service)
INFO - Configuring Service(id=Default Transaction Manager,
type=TransactionManager, provider-id=Default Transaction Manager)
INFO - Creating TransactionManager(id=Default Transaction Manager)
INFO - Creating SecurityService(id=Default Security Service)
INFO - Configuring enterprise application:
/home/kubam/workspaces/java/various/jee-examples/stockapp/stockapp-ejb-
openejbtest/DozerQuotationConverterIntegrationTest
INFO - Auto-deploying ejb DozerConverterCache: EjbDeployment(deployment-
id=DozerConverterCache)
INFO - Auto-deploying ejb DozerQuotationConverter: EjbDeployment(deployment-
id=DozerQuotationConverter)
INFO - Configuring Service(id=Default Managed Container, type=Container,
provider-id=Default ManagedContainer)
INFO - Auto-creating a container for bean
pl.marchwicki.jee.stockapp.ejb.DozerQuotationConverterIntegrationTest:
Container(type=MANAGED, id=Default Managed Container)
INFO - Creating Container(id=Default Managed Container)
twitter: @kubem
@RunWi t h( Appl i cat i onComposer . cl ass)
publ i c cl ass Hel l oWorl dServi ceInt egrat i onTest {
@EJB
Hel l oWor l dSer vi ceLocal hel l oWor l dSer vi ce;
@Test
publ i c voi d shoul dRet urnHel l o( ) {
a s s e r t Eq ua l s ( he l l o Wo r l d Se r v i c e . s a y He l l o ( " Ja kub" ) , " He l l o !
Ja kub" ) ;
}
/ / . . .
}
@RunWi t h( Appl i cat i onComposer . cl ass)
publ i c cl ass Hel l oWorl dServi ceInt egrat i onTest {
@EJB
Hel l oWor l dSer vi ceLocal hel l oWor l dSer vi ce;
@Test
publ i c voi d shoul dRet urnHel l o( ) {
a s s e r t Eq ua l s ( he l l o Wo r l d Se r v i c e . s a y He l l o ( " Ja kub" ) , " He l l o !
Ja kub" ) ;
}
/ / . . .
}
twitter: @kubem
@RunWi t h( Appl i cat i onComposer . cl ass)
publ i c cl ass Audi t MessageRecei verTest {
f i nal St ri ng ori gi nal Test Message = "Hel l o Worl d! ";
/ / . .
@Per si st enceCont ext
Ent i t yManager em;
@Test
publ i c voi d processQueue( ) t hrows JMSExcept i on {
Li st <Audi t Log> l i st = em. cr eat eQuer y( " f r om Audi t Log" ,
Audi t Log. cl ass) . get Resul t Li st ( ) ;
a s s e r t No t Nul l ( l i s t ) ;
a s s e r t Eq ua l s ( 1 , l i s t . s i z e ( ) ) ;
a s s e r t Eq ua l s ( o r i g i na l Te s t Me s s a g e , l i s t . g e t ( 0 ) . g e t Me s s a g e ( ) ) ;
}
/ / . .
}
@RunWi t h( Appl i cat i onComposer . cl ass)
publ i c cl ass Audi t MessageRecei verTest {
f i nal St ri ng ori gi nal Test Message = "Hel l o Worl d! ";
/ / . .
@Per si st enceCont ext
Ent i t yManager em;
@Test
publ i c voi d processQueue( ) t hrows JMSExcept i on {
Li st <Audi t Log> l i st = em. cr eat eQuer y( " f r om Audi t Log" ,
Audi t Log. cl ass) . get Resul t Li st ( ) ;
a s s e r t No t Nul l ( l i s t ) ;
a s s e r t Eq ua l s ( 1 , l i s t . s i z e ( ) ) ;
a s s e r t Eq ua l s ( o r i g i na l Te s t Me s s a g e , l i s t . g e t ( 0 ) . g e t Me s s a g e ( ) ) ;
}
/ / . .
}
twitter: @kubem
@RunWi t h( Appl i cat i onComposer . cl ass)
publ i c cl ass Audi t MessageProcessorTest {
@Resour ce( name = " Connect i onFact or y" , mappedName =
" Connect i onFact or y" )
Connect i onFact or y connect i onFact or y;
@Resour ce( name = " queue/ audi t " , mappedName = " queue/ audi t " )
Queue queue;
@Test ( t i meout = 2000)
publ i c voi d processQueue( ) t hrows Except i on {
f i nal Connect i on connect i on =
connect i onFact ory. creat eConnect i on( ) ;
connect i on. st ar t ( ) ;
f i nal Sessi on sessi on = connect i on. creat eSessi on( f al se,
Sessi on. AUTO_ ACKNOWLEDGE) ;
f i nal MessageConsumer i ncomi ng =
sessi on. creat eConsumer( queue) ;
Message r ecei ve = i ncomi ng. r ecei ve( ) ;
a s s e r t Tha t ( r e c e i v e , new IsInst anceOf (Text Message. cl ass));
a s s e r t Eq ua l s ( o r i g i na l Te s t Me s s a g e , ( ( Te x t Me s s a g e )
r e c e i v e ) . g e t Te x t ( ) ) ;
}
/ / . . .
}
@RunWi t h( Appl i cat i onComposer . cl ass)
publ i c cl ass Audi t MessageProcessorTest {
@Resour ce( name = " Connect i onFact or y" , mappedName =
" Connect i onFact or y" )
Connect i onFact or y connect i onFact or y;
@Resour ce( name = " queue/ audi t " , mappedName = " queue/ audi t " )
Queue queue;
@Test ( t i meout = 2000)
publ i c voi d processQueue( ) t hrows Except i on {
f i nal Connect i on connect i on =
connect i onFact ory. creat eConnect i on( ) ;
connect i on. st ar t ( ) ;
f i nal Sessi on sessi on = connect i on. creat eSessi on( f al se,
Sessi on. AUTO_ ACKNOWLEDGE) ;
f i nal MessageConsumer i ncomi ng =
sessi on. creat eConsumer( queue) ;
Message r ecei ve = i ncomi ng. r ecei ve( ) ;
a s s e r t Tha t ( r e c e i v e , new IsInst anceOf (Text Message. cl ass));
a s s e r t Eq ua l s ( o r i g i na l Te s t Me s s a g e , ( ( Te x t Me s s a g e )
r e c e i v e ) . g e t Te x t ( ) ) ;
}
/ / . . .
}
twitter: @kubem
@RunWi t h( Appl i cat i onComposer . cl ass)
publ i c cl ass Hel l oWorl dServi ceInt egrat i onTest {
@Test
publ i c voi d shoul dCal l WebServi ce( ) t hrows Except i on {
URL wsdl Document Locat i on =
new URL( "ht t p: //127. 0. 0. 1: 4204/modul e/Hel l oWorl dServi ce?
wsdl ") ;
St r i ng namespaceURI =
" ht t p: / / hw. ej b. st ockapp. j ee. mar chwi cki . pl / " ;
St r i ng ser vi cePar t = " Hel l oWor l dSer vi ceSer vi ce" ;
QName ser vi ceQN = new QName( namespaceURI, servi cePart ) ;
Ser vi ce ser vi ce = Ser vi ce. c r e a t e ( ws d l Do c ume nt Lo c a t i o n,
s e r v i c e QN) ;
Hel l oWor l dSer vi ceLocal hel l oWor l d =
ser vi ce. get Por t ( Hel l oWor l dSer vi ceLocal . cl ass) ;
St r i ng s = hel l oWor l d. sayHel l o( " Jakub" ) ;
a s s e r t Eq ua l s ( " He l l o ! Ja kub" , s ) ;
}
/ / . . .
}
@RunWi t h( Appl i cat i onComposer . cl ass)
publ i c cl ass Hel l oWorl dServi ceInt egrat i onTest {
@Test
publ i c voi d shoul dCal l WebServi ce( ) t hrows Except i on {
URL wsdl Document Locat i on =
new URL( "ht t p: //127. 0. 0. 1: 4204/modul e/Hel l oWorl dServi ce?
wsdl ") ;
St r i ng namespaceURI =
" ht t p: / / hw. ej b. st ockapp. j ee. mar chwi cki . pl / " ;
St r i ng ser vi cePar t = " Hel l oWor l dSer vi ceSer vi ce" ;
QName ser vi ceQN = new QName( namespaceURI, servi cePart ) ;
Ser vi ce ser vi ce = Ser vi ce. c r e a t e ( ws d l Do c ume nt Lo c a t i o n,
s e r v i c e QN) ;
Hel l oWor l dSer vi ceLocal hel l oWor l d =
ser vi ce. get Por t ( Hel l oWor l dSer vi ceLocal . cl ass) ;
St r i ng s = hel l oWor l d. sayHel l o( " Jakub" ) ;
a s s e r t Eq ua l s ( " He l l o ! Ja kub" , s ) ;
}
/ / . . .
}
twitter: @kubem
The Bad
Differences between
containers
Vagueness of the EJB
spec
No test with the actual
server
twitter: @kubem
JNDI tree
• {deploymentId} / {interfaceClass}
• {appName} / {moduleName} / {beanName}
But where it’s localted?
• java: app/*
• java: comp/env/*
• java: global/*
twitter: @kubem
Multiple names
publ i c i nt erf ace Servi ce
{
publ i c St ri ng
hel l o( ) ;
}
publ i c i nt erf ace Servi ce
{
publ i c St ri ng
hel l o( ) ;
}
twitter: @kubem
Multiple names
publ i c i nt erf ace Servi ce
{
publ i c St ri ng
hel l o( ) ;
}
publ i c i nt erf ace Servi ce
{
publ i c St ri ng
hel l o( ) ;
} @St at el ess
publ i c cl ass MyServi ce i mpl ement s
Servi ce {
publ i c St ri ng hel l o( ) {
ret urn "Hel l o worl d! ";
}
}
@St at el ess
publ i c cl ass MyServi ce i mpl ement s
Servi ce {
publ i c St ri ng hel l o( ) {
ret urn "Hel l o worl d! ";
}
}
twitter: @kubem
Multiple names
publ i c i nt erf ace Servi ce
{
publ i c St ri ng
hel l o( ) ;
}
publ i c i nt erf ace Servi ce
{
publ i c St ri ng
hel l o( ) ;
} @St at el ess
publ i c cl ass MyServi ce i mpl ement s
Servi ce {
publ i c St ri ng hel l o( ) {
ret urn "Hel l o worl d! ";
}
}
@St at el ess
publ i c cl ass MyServi ce i mpl ement s
Servi ce {
publ i c St ri ng hel l o( ) {
ret urn "Hel l o worl d! ";
}
}
@St at el ess
publ i c cl ass MyOt herServi ce i mpl ement s
Servi ce {
publ i c St ri ng hel l o( ) {
ret urn "Hel l o GeeCON! ";
}
}
@St at el ess
publ i c cl ass MyOt herServi ce i mpl ement s
Servi ce {
publ i c St ri ng hel l o( ) {
ret urn "Hel l o GeeCON! ";
}
}
twitter: @kubem
Multiple names
publ i c i nt erf ace Servi ce
{
publ i c St ri ng
hel l o( ) ;
}
publ i c i nt erf ace Servi ce
{
publ i c St ri ng
hel l o( ) ;
} @St at el ess
publ i c cl ass MyServi ce i mpl ement s
Servi ce {
publ i c St ri ng hel l o( ) {
ret urn "Hel l o worl d! ";
}
}
@St at el ess
publ i c cl ass MyServi ce i mpl ement s
Servi ce {
publ i c St ri ng hel l o( ) {
ret urn "Hel l o worl d! ";
}
}
@St at el ess
publ i c cl ass MyOt herServi ce i mpl ement s
Servi ce {
publ i c St ri ng hel l o( ) {
ret urn "Hel l o GeeCON! ";
}
}
@St at el ess
publ i c cl ass MyOt herServi ce i mpl ement s
Servi ce {
publ i c St ri ng hel l o( ) {
ret urn "Hel l o GeeCON! ";
}
}
@St ar t up
@Si ngl et on
publ i c cl ass Cl i ent {
@EJB
Ser vi ce ser vi ce;
@Post Const r uct
publ i c voi d i ni t ( ) {
Syst em. o ut . p r i nt l n( s e r v i c e . he l l o ( ) ) ;
}
}
@St ar t up
@Si ngl et on
publ i c cl ass Cl i ent {
@EJB
Ser vi ce ser vi ce;
@Post Const r uct
publ i c voi d i ni t ( ) {
Syst em. o ut . p r i nt l n( s e r v i c e . he l l o ( ) ) ;
}
}
twitter: @kubem
DEPLOYMENTS IN ERROR:
Deployment "vfs:///opt/java/jboss-
6.1.0.Final/server/default/deploy/module.jar" is in error due to the
following reason(s): java.lang.RuntimeException: Specified reference
[EJB Reference: beanInterface 'pl.marchwicki.jee6.Service', beanName
'null', mappedName 'null', lookupName 'null', owning unit
'ComponentDeploymentContext@2078856098{org.jboss.metadata.ejb.jboss.JBo
ssEnterpriseBeanMetaData.Client}'] was matched by more than one EJB:
[org.jboss.metadata.ejb.jboss.JBossSessionBean31MetaData@8b7ff749{MySer
vice},
org.jboss.metadata.ejb.jboss.JBossSessionBean31MetaData@5baed971{MyOthe
rService}]. Specify beanName explciitly or ensure beanInterface is
unique.
DEPLOYMENTS IN ERROR:
Deployment "vfs:///opt/java/jboss-
6.1.0.Final/server/default/deploy/module.jar" is in error due to the
following reason(s): java.lang.RuntimeException: Specified reference
[EJB Reference: beanInterface 'pl.marchwicki.jee6.Service', beanName
'null', mappedName 'null', lookupName 'null', owning unit
'ComponentDeploymentContext@2078856098{org.jboss.metadata.ejb.jboss.JBo
ssEnterpriseBeanMetaData.Client}'] was matched by more than one EJB:
[org.jboss.metadata.ejb.jboss.JBossSessionBean31MetaData@8b7ff749{MySer
vice},
org.jboss.metadata.ejb.jboss.JBossSessionBean31MetaData@5baed971{MyOthe
rService}]. Specify beanName explciitly or ensure beanInterface is
unique.
twitter: @kubem
INFO: Created Ejb(deployment-id=Client, ejb-name=Client, container=My
Singleton Container)
May 11, 013 4:23:24 PM org.apache.openejb.assembler.classic.Assembler
startEjbs
INFO: Started Ejb(deployment-id=MyService, ejb-name=MyService,
container=My Stateless Container)
May 11, 2013 4:23:24 PM org.apache.openejb.assembler.classic.Assembler
startEjbs
INFO: Started Ejb(deployment-id=MyOtherService,
ejb-name=MyOtherService, container=My Stateless Container)
Hello world!
INFO: Created Ejb(deployment-id=Client, ejb-name=Client, container=My
Singleton Container)
May 11, 013 4:23:24 PM org.apache.openejb.assembler.classic.Assembler
startEjbs
INFO: Started Ejb(deployment-id=MyService, ejb-name=MyService,
container=My Stateless Container)
May 11, 2013 4:23:24 PM org.apache.openejb.assembler.classic.Assembler
startEjbs
INFO: Started Ejb(deployment-id=MyOtherService,
ejb-name=MyOtherService, container=My Stateless Container)
Hello world!
twitter: @kubem
Different implementations
@Xml Root El ement
publ i c cl ass Todo {
pri vat e l ong i d;
@Not Nul l
@Si ze( mi n = 1)
pri vat e St ri ng t i t l e;
pri vat e l ong order;
pri vat e bool ean compl et ed;
/ / . . .
}
@Xml Root El ement
publ i c cl ass Todo {
pri vat e l ong i d;
@Not Nul l
@Si ze( mi n = 1)
pri vat e St ri ng t i t l e;
pri vat e l ong order;
pri vat e bool ean compl et ed;
/ / . . .
}
twitter: @kubem
Different implementations
@Xml Root El ement
publ i c cl ass Todo {
pri vat e l ong i d;
@Not Nul l
@Si ze( mi n = 1)
pri vat e St ri ng t i t l e;
pri vat e l ong order;
pri vat e bool ean compl et ed;
/ / . . .
}
@Xml Root El ement
publ i c cl ass Todo {
pri vat e l ong i d;
@Not Nul l
@Si ze( mi n = 1)
pri vat e St ri ng t i t l e;
pri vat e l ong order;
pri vat e bool ean compl et ed;
/ / . . .
}
@Pat h( " / t odos" )
@Pr oduces( Medi aType. APPLICATION_ JSON)
publ i c cl ass TodoResource {
@GET
publ i c Li st <Todo> get Al l ( ) {
ret urn st ore. get Al l ( ) ;
}
@GET
@Pat h( " / { i d} " )
publ i c Todo get ( @Pat hParam( "i d") l ong
i d) {
ret urn st ore. get ( i d) ;
}
/ / . . .
}
@Pat h( " / t odos" )
@Pr oduces( Medi aType. APPLICATION_ JSON)
publ i c cl ass TodoResource {
@GET
publ i c Li st <Todo> get Al l ( ) {
ret urn st ore. get Al l ( ) ;
}
@GET
@Pat h( " / { i d} " )
publ i c Todo get ( @Pat hParam( "i d") l ong
i d) {
ret urn st ore. get ( i d) ;
}
/ / . . .
}
twitter: @kubem
GET /todos/1 HTTP/1.1
Host: localhost
HTTP/1.1 200 OK
{
"id": 1,
"title": "First todo",
"order": 1,
"completed": false
}
GET /todos/1 HTTP/1.1
Host: localhost
HTTP/1.1 200 OK
{
"id": 1,
"title": "First todo",
"order": 1,
"completed": false
}
GET /todos HTTP/1.1
Host: localhost
HTTP/1.1 200 OK
[
{
"id": 1,
"title": "First todo",
"order": 1,
"completed": false
},
{
"id": 2,
"title": "Second todo",
"order": 2,
"completed": false
}
]
GET /todos HTTP/1.1
Host: localhost
HTTP/1.1 200 OK
[
{
"id": 1,
"title": "First todo",
"order": 1,
"completed": false
},
{
"id": 2,
"title": "Second todo",
"order": 2,
"completed": false
}
]
twitter: @kubem
GET /todos/1 HTTP/1.1
Host: localhost
HTTP/1.1 200 OK
{
todo: {
"id": 1,
"title": "First todo",
"order": 1,
"completed": false
}
}
GET /todos/1 HTTP/1.1
Host: localhost
HTTP/1.1 200 OK
{
todo: {
"id": 1,
"title": "First todo",
"order": 1,
"completed": false
}
}
GET /todos HTTP/1.1
Host: localhost
HTTP/1.1 200 OK
{
todo: [
{
"id": 1,
"title": "First todo",
"order": 1,
"completed": false
},
{
"id": 2,
"title": "Second todo",
"order": 2,
"completed": false
}
]
}
GET /todos HTTP/1.1
Host: localhost
HTTP/1.1 200 OK
{
todo: [
{
"id": 1,
"title": "First todo",
"order": 1,
"completed": false
},
{
"id": 2,
"title": "Second todo",
"order": 2,
"completed": false
}
]
}
twitter: @kubem
GET /todos/1 HTTP/1.1
Host: localhost
HTTP/1.1 200 OK
{
todo: {
"id": 1,
"title": "First todo",
"order": 1,
"completed": false
}
}
GET /todos/1 HTTP/1.1
Host: localhost
HTTP/1.1 200 OK
{
todo: {
"id": 1,
"title": "First todo",
"order": 1,
"completed": false
}
}
GET /todos HTTP/1.1
Host: localhost
HTTP/1.1 200 OK
{
todo: [
{
"id": 1,
"title": "First todo",
"order": 1,
"completed": false
},
{
"id": 2,
"title": "Second todo",
"order": 2,
"completed": false
}
]
}
GET /todos HTTP/1.1
Host: localhost
HTTP/1.1 200 OK
{
todo: [
{
"id": 1,
"title": "First todo",
"order": 1,
"completed": false
},
{
"id": 2,
"title": "Second todo",
"order": 2,
"completed": false
}
]
}
twitter: @kubem
The Ugly
Loads of boilerplate code
Tests only EJBs
Never deployed
twitter: @kubem
@RunWi t h( Appl i cat i onComposer . cl ass)
publ i c cl ass Audi t MessageRecei verTest {
f i nal St ri ng ori gi nal Test Message = "Hel l o Worl d! ";
//. .
@Per si st enceCont ext
Ent i t yManager em;
@Test
publ i c voi d processQueue( ) t hrows JMSExcept i on {
Li st <Audi t Log> l i st = em. cr eat eQuer y( " f r om Audi t Log" ,
Audi t Log. cl ass) . get Resul t Li st ( ) ;
a s s e r t No t Nul l ( l i s t ) ;
a s s e r t Eq ua l s ( 1 , l i s t . s i z e ( ) ) ;
a s s e r t Eq ua l s ( o r i g i na l Te s t Me s s a g e , l i s t . g e t ( 0 ) . g e t Me s s a g e ( ) ) ;
}
//. .
}
@RunWi t h( Appl i cat i onComposer . cl ass)
publ i c cl ass Audi t MessageRecei verTest {
f i nal St ri ng ori gi nal Test Message = "Hel l o Worl d! ";
//. .
@Per si st enceCont ext
Ent i t yManager em;
@Test
publ i c voi d processQueue( ) t hrows JMSExcept i on {
Li st <Audi t Log> l i st = em. cr eat eQuer y( " f r om Audi t Log" ,
Audi t Log. cl ass) . get Resul t Li st ( ) ;
a s s e r t No t Nul l ( l i s t ) ;
a s s e r t Eq ua l s ( 1 , l i s t . s i z e ( ) ) ;
a s s e r t Eq ua l s ( o r i g i na l Te s t Me s s a g e , l i s t . g e t ( 0 ) . g e t Me s s a g e ( ) ) ;
}
//. .
}
Configuration
twitter: @kubem
@RunWi t h( Appl i cat i onComposer . cl ass)
publ i c cl ass Audi t MessageRecei verTest {
@Modul e
publ i c Ej bJar modul e( ) {
f i nal Ej bJar ej bJar = new Ej bJar( ) ;
ej bJar . addEnt er pr i seBean( new
St at el essBean( Audi t MessageProcessi ng. cl ass) ) ;
ej bJar . addEnt er pr i seBean( new
St at el essBean( Audi t LoggerServi ce. cl ass) ) ;
ej bJar . addEnt er pr i seBean( new
MessageDri venBean( Audi t i ngMessageLi st erner. cl ass) ) ;
ret urn ej bJar;
}
//. .
@RunWi t h( Appl i cat i onComposer . cl ass)
publ i c cl ass Audi t MessageRecei verTest {
@Modul e
publ i c Ej bJar modul e( ) {
f i nal Ej bJar ej bJar = new Ej bJar( ) ;
ej bJar . addEnt er pr i seBean( new
St at el essBean( Audi t MessageProcessi ng. cl ass) ) ;
ej bJar . addEnt er pr i seBean( new
St at el essBean( Audi t LoggerServi ce. cl ass) ) ;
ej bJar . addEnt er pr i seBean( new
MessageDri venBean( Audi t i ngMessageLi st erner. cl ass) ) ;
ret urn ej bJar;
}
//. .
twitter: @kubem
@RunWi t h( Appl i cat i onComposer . cl ass)
publ i c cl ass Audi t MessageRecei verTest {
//. .
@Modul e
publ i c Persi st enceUni t persi st ence( ) {
Per si st enceUni t uni t = new Persi st enceUni t ( "st ockapp- audi t ") ;
uni t . set Jt aDat aSour ce( " Def aul t DS" ) ;
uni t . set Pr ovi der ( Hi ber nat ePer si st ence. cl ass) ;
uni t . addCl ass( Audi t Log. cl ass) ;
Pr oper t i es dbPr oper t i es = new Propert i es( ) ;
dbPr oper t i es. set Pr oper t y( " hi ber nat e. hbm2ddl . aut o" , " cr eat e-
dr op" ) ;
dbPr oper t i es. set Pr oper t y( " hi ber nat e. di al ect " ,
" or g. hi ber nat e. di al ect . HSQLDi al ect " ) ;
dbPr oper t i es. set Pr oper t y" hi ber nat e. use_sql _comment s" , " t r ue" ) ;
dbPr oper t i es. set Pr oper t y( " hi ber nat e. show_sql " , " t r ue" ) ;
dbPr oper t i es. set Pr oper t y( " hi ber nat e. f or mat _sql " , " t r ue" ) ;
uni t . set Pr oper t i es( dbPr oper t i es) ;
ret urn uni t ;
}
//. .
@RunWi t h( Appl i cat i onComposer . cl ass)
publ i c cl ass Audi t MessageRecei verTest {
//. .
@Modul e
publ i c Persi st enceUni t persi st ence( ) {
Per si st enceUni t uni t = new Persi st enceUni t ( "st ockapp- audi t ") ;
uni t . set Jt aDat aSour ce( " Def aul t DS" ) ;
uni t . set Pr ovi der ( Hi ber nat ePer si st ence. cl ass) ;
uni t . addCl ass( Audi t Log. cl ass) ;
Pr oper t i es dbPr oper t i es = new Propert i es( ) ;
dbPr oper t i es. set Pr oper t y( " hi ber nat e. hbm2ddl . aut o" , " cr eat e-
dr op" ) ;
dbPr oper t i es. set Pr oper t y( " hi ber nat e. di al ect " ,
" or g. hi ber nat e. di al ect . HSQLDi al ect " ) ;
dbPr oper t i es. set Pr oper t y" hi ber nat e. use_sql _comment s" , " t r ue" ) ;
dbPr oper t i es. set Pr oper t y( " hi ber nat e. show_sql " , " t r ue" ) ;
dbPr oper t i es. set Pr oper t y( " hi ber nat e. f or mat _sql " , " t r ue" ) ;
uni t . set Pr oper t i es( dbPr oper t i es) ;
ret urn uni t ;
}
//. .
twitter: @kubem
@RunWi t h( Appl i cat i onComposer . cl ass)
publ i c cl ass Audi t MessageRecei verTest {
//. .
@Conf i gur at i on
publ i c Propert i es conf i g( ) t hrows Except i on {
Pr oper t i es p = new Propert i es( ) ;
p. put ( " Def aul t DS" , " new: / / Resour ce?t ype=Dat aSour ce" ) ;
p. put ( " Def aul t DS. JdbcDr i ver " , " or g. hsql db. j dbcDr i ver " ) ;
p. put ( " Def aul t DS. JdbcUr l " , " j dbc: hsql db: mem: t est db" ) ;
ret urn p;
}
//. .
@RunWi t h( Appl i cat i onComposer . cl ass)
publ i c cl ass Audi t MessageRecei verTest {
//. .
@Conf i gur at i on
publ i c Propert i es conf i g( ) t hrows Except i on {
Pr oper t i es p = new Propert i es( ) ;
p. put ( " Def aul t DS" , " new: / / Resour ce?t ype=Dat aSour ce" ) ;
p. put ( " Def aul t DS. JdbcDr i ver " , " or g. hsql db. j dbcDr i ver " ) ;
p. put ( " Def aul t DS. JdbcUr l " , " j dbc: hsql db: mem: t est db" ) ;
ret urn p;
}
//. .
twitter: @kubem
Test only EJB
It’s not a real application server
Webservices: Apache CXF
JMS: Apache MQ
JPA: OpenJPA
Hibernate
(any provider)
Where we are now?
twitter: @kubem
The aliens have landed
• Arquillian is a testing framework
• There are runners…
• Containers…
• & Enrichers
twitter: @kubem
The aliens have landed
• Arquillian is a testing framework
• There are runners…
– JUnit
– TestNG
• Containers…
• & Enrichers
twitter: @kubem
The aliens have landed
• Arquillian is a testing framework
• There are runners…
• Containers…
– Weld
– Tomcat
– JBoss
– Glassfish
• & Enrichers
twitter: @kubem
The aliens have landed
• Arquillian is a testing framework
• There are runners…
• Containers…
• & Enrichers
– glue layer between
your code and
the container:
inject, track results
twitter: @kubem
A natural evolution
twitter: @kubem
The are three modes
• Embedded
– You run your app server together with your code, in a
single JVM
• Managed
– Arquillian starts and stops your nodes, together with an
app, in separate JVMs
• Remote
– Everything is remotly deployed
twitter: @kubem
And four ways for
communicating results
• Local
– Same JVM, local bindings
• Servlet 2.5
– Pre JEE-6 containers
• Servlet 3.0
– Leveraging async servlets
• JMX
– Jboss AS 7 way
How it works in practice
twitter: @kubem
Why we do it?
• Real test with real services (no mocks
movement)
• With real environment
• Short feedback cycle
twitter: @kubem
What’s next
• Persitence Extension (DBUnit)
• GWT Extension
• JSFUnit
• BPEL testing
• Performance
• … ?
twitter: @kubem
Call for arms
Arquillian Test Porting Initiative
twitter: @kubem
https://issues.apache.org/jira/
browse/TOMEE-746
http://tomee.apache.org/dev/
arquillian-test-porting-initiative.html
twitter: @kubem
Projects to tackle
• Active MQ
• Apache CXF
• TomEE & OpenEJB
• MyFaces
• OpenWenBeans
• BVal
Lemme show you
twitter: @kubem
You can innovate on
nonfunctional areas, such as
devops, logging, metrics, etc, if
your core business needs to be
more conservative.
twitter: @kubem
Innovation comes not just from
using new technologies, but also
from using new techniques with
old boring technologies
twitter: @kubem
Questions

Más contenido relacionado

La actualidad más candente

QA Fest 2019. Saar Rachamim. Developing Tools, While Testing
QA Fest 2019. Saar Rachamim. Developing Tools, While TestingQA Fest 2019. Saar Rachamim. Developing Tools, While Testing
QA Fest 2019. Saar Rachamim. Developing Tools, While TestingQAFest
 
Programação Assíncrona com Asyncio
Programação Assíncrona com AsyncioProgramação Assíncrona com Asyncio
Programação Assíncrona com AsyncioAllisson Azevedo
 
The Ring programming language version 1.10 book - Part 92 of 212
The Ring programming language version 1.10 book - Part 92 of 212The Ring programming language version 1.10 book - Part 92 of 212
The Ring programming language version 1.10 book - Part 92 of 212Mahmoud Samir Fayed
 
SecureSocial - Authentication for Play Framework
SecureSocial - Authentication for Play FrameworkSecureSocial - Authentication for Play Framework
SecureSocial - Authentication for Play Frameworkjaliss
 
Automated tests - facts and myths
Automated tests - facts and mythsAutomated tests - facts and myths
Automated tests - facts and mythsWojciech Sznapka
 
Puppet: What _not_ to do
Puppet: What _not_ to doPuppet: What _not_ to do
Puppet: What _not_ to doPuppet
 
PuppetCamp Ghent - What Not to Do with Puppet
PuppetCamp Ghent - What Not to Do with PuppetPuppetCamp Ghent - What Not to Do with Puppet
PuppetCamp Ghent - What Not to Do with PuppetWalter Heck
 
Lightning fast with Varnish
Lightning fast with VarnishLightning fast with Varnish
Lightning fast with VarnishVarnish Software
 
[Webinar] An Hour with the CTO: All About APIs and the Nuxeo Platform
[Webinar] An Hour with the CTO: All About APIs and the Nuxeo Platform[Webinar] An Hour with the CTO: All About APIs and the Nuxeo Platform
[Webinar] An Hour with the CTO: All About APIs and the Nuxeo PlatformNuxeo
 
Puppet Module Reusability - What I Learned from Shipping to the Forge
Puppet Module Reusability - What I Learned from Shipping to the ForgePuppet Module Reusability - What I Learned from Shipping to the Forge
Puppet Module Reusability - What I Learned from Shipping to the ForgePuppet
 
jSession #4 - Maciej Puchalski - Zaawansowany retrofit
jSession #4 - Maciej Puchalski - Zaawansowany retrofitjSession #4 - Maciej Puchalski - Zaawansowany retrofit
jSession #4 - Maciej Puchalski - Zaawansowany retrofitjSession
 
JJUG CCC 2011 Spring
JJUG CCC 2011 SpringJJUG CCC 2011 Spring
JJUG CCC 2011 SpringKiyotaka Oku
 
Parallel Computing With Dask - PyDays 2017
Parallel Computing With Dask - PyDays 2017Parallel Computing With Dask - PyDays 2017
Parallel Computing With Dask - PyDays 2017Christian Aichinger
 
Neotool (using py2neo from the command line)
Neotool (using py2neo from the command line)Neotool (using py2neo from the command line)
Neotool (using py2neo from the command line)Nigel Small
 
Visualizing ORACLE performance data with R @ #C16LV
Visualizing ORACLE performance data with R @ #C16LVVisualizing ORACLE performance data with R @ #C16LV
Visualizing ORACLE performance data with R @ #C16LVMaxym Kharchenko
 

La actualidad más candente (20)

Tugas 2
Tugas 2Tugas 2
Tugas 2
 
QA Fest 2019. Saar Rachamim. Developing Tools, While Testing
QA Fest 2019. Saar Rachamim. Developing Tools, While TestingQA Fest 2019. Saar Rachamim. Developing Tools, While Testing
QA Fest 2019. Saar Rachamim. Developing Tools, While Testing
 
Programação Assíncrona com Asyncio
Programação Assíncrona com AsyncioProgramação Assíncrona com Asyncio
Programação Assíncrona com Asyncio
 
The Ring programming language version 1.10 book - Part 92 of 212
The Ring programming language version 1.10 book - Part 92 of 212The Ring programming language version 1.10 book - Part 92 of 212
The Ring programming language version 1.10 book - Part 92 of 212
 
SecureSocial - Authentication for Play Framework
SecureSocial - Authentication for Play FrameworkSecureSocial - Authentication for Play Framework
SecureSocial - Authentication for Play Framework
 
Automated tests - facts and myths
Automated tests - facts and mythsAutomated tests - facts and myths
Automated tests - facts and myths
 
Puppet: What _not_ to do
Puppet: What _not_ to doPuppet: What _not_ to do
Puppet: What _not_ to do
 
PuppetCamp Ghent - What Not to Do with Puppet
PuppetCamp Ghent - What Not to Do with PuppetPuppetCamp Ghent - What Not to Do with Puppet
PuppetCamp Ghent - What Not to Do with Puppet
 
Fake My Party
Fake My PartyFake My Party
Fake My Party
 
Lightning fast with Varnish
Lightning fast with VarnishLightning fast with Varnish
Lightning fast with Varnish
 
[Webinar] An Hour with the CTO: All About APIs and the Nuxeo Platform
[Webinar] An Hour with the CTO: All About APIs and the Nuxeo Platform[Webinar] An Hour with the CTO: All About APIs and the Nuxeo Platform
[Webinar] An Hour with the CTO: All About APIs and the Nuxeo Platform
 
Gevent rabbit rpc
Gevent rabbit rpcGevent rabbit rpc
Gevent rabbit rpc
 
Assignment6
Assignment6Assignment6
Assignment6
 
Puppet Module Reusability - What I Learned from Shipping to the Forge
Puppet Module Reusability - What I Learned from Shipping to the ForgePuppet Module Reusability - What I Learned from Shipping to the Forge
Puppet Module Reusability - What I Learned from Shipping to the Forge
 
jSession #4 - Maciej Puchalski - Zaawansowany retrofit
jSession #4 - Maciej Puchalski - Zaawansowany retrofitjSession #4 - Maciej Puchalski - Zaawansowany retrofit
jSession #4 - Maciej Puchalski - Zaawansowany retrofit
 
JJUG CCC 2011 Spring
JJUG CCC 2011 SpringJJUG CCC 2011 Spring
JJUG CCC 2011 Spring
 
Parallel Computing With Dask - PyDays 2017
Parallel Computing With Dask - PyDays 2017Parallel Computing With Dask - PyDays 2017
Parallel Computing With Dask - PyDays 2017
 
Neotool (using py2neo from the command line)
Neotool (using py2neo from the command line)Neotool (using py2neo from the command line)
Neotool (using py2neo from the command line)
 
Visualizing ORACLE performance data with R @ #C16LV
Visualizing ORACLE performance data with R @ #C16LVVisualizing ORACLE performance data with R @ #C16LV
Visualizing ORACLE performance data with R @ #C16LV
 
Cooking pies with Celery
Cooking pies with CeleryCooking pies with Celery
Cooking pies with Celery
 

Destacado

Análise da estrutura e conteúdo dos poemas
Análise da estrutura e conteúdo dos poemasAnálise da estrutura e conteúdo dos poemas
Análise da estrutura e conteúdo dos poemasPéricles Penuel
 
Caderno de poemas
Caderno  de poemasCaderno  de poemas
Caderno de poemasAline Cruz
 
Ricardo Reis - Análise do poema "Vem sentar-te comigo, Lídia, à beira do rio"...
Ricardo Reis - Análise do poema "Vem sentar-te comigo, Lídia, à beira do rio"...Ricardo Reis - Análise do poema "Vem sentar-te comigo, Lídia, à beira do rio"...
Ricardo Reis - Análise do poema "Vem sentar-te comigo, Lídia, à beira do rio"...FilipaFonseca
 
Análise do poema Nao sei quantas almas tenho
Análise do poema Nao sei quantas almas tenhoAnálise do poema Nao sei quantas almas tenho
Análise do poema Nao sei quantas almas tenhoRicardo Santos
 
LITERATURA: ESCOLAS LITERÁRIAS
LITERATURA: ESCOLAS LITERÁRIASLITERATURA: ESCOLAS LITERÁRIAS
LITERATURA: ESCOLAS LITERÁRIASAmelia Barros
 
Cronicas
CronicasCronicas
Cronicaskadjaxh
 
Study: The Future of VR, AR and Self-Driving Cars
Study: The Future of VR, AR and Self-Driving CarsStudy: The Future of VR, AR and Self-Driving Cars
Study: The Future of VR, AR and Self-Driving CarsLinkedIn
 

Destacado (14)

Construção de poemas
Construção de poemasConstrução de poemas
Construção de poemas
 
A lingua portuguesa agradece
A lingua portuguesa agradeceA lingua portuguesa agradece
A lingua portuguesa agradece
 
Provérbios
ProvérbiosProvérbios
Provérbios
 
Convite
ConviteConvite
Convite
 
Formas de poemas
Formas de poemasFormas de poemas
Formas de poemas
 
Análise da estrutura e conteúdo dos poemas
Análise da estrutura e conteúdo dos poemasAnálise da estrutura e conteúdo dos poemas
Análise da estrutura e conteúdo dos poemas
 
Caderno de poemas
Caderno  de poemasCaderno  de poemas
Caderno de poemas
 
Literatura brasileira resumo
Literatura brasileira resumoLiteratura brasileira resumo
Literatura brasileira resumo
 
Ricardo Reis - Análise do poema "Vem sentar-te comigo, Lídia, à beira do rio"...
Ricardo Reis - Análise do poema "Vem sentar-te comigo, Lídia, à beira do rio"...Ricardo Reis - Análise do poema "Vem sentar-te comigo, Lídia, à beira do rio"...
Ricardo Reis - Análise do poema "Vem sentar-te comigo, Lídia, à beira do rio"...
 
Análise do poema Nao sei quantas almas tenho
Análise do poema Nao sei quantas almas tenhoAnálise do poema Nao sei quantas almas tenho
Análise do poema Nao sei quantas almas tenho
 
LITERATURA: ESCOLAS LITERÁRIAS
LITERATURA: ESCOLAS LITERÁRIASLITERATURA: ESCOLAS LITERÁRIAS
LITERATURA: ESCOLAS LITERÁRIAS
 
Cronicas
CronicasCronicas
Cronicas
 
Análise de poemas
Análise de poemasAnálise de poemas
Análise de poemas
 
Study: The Future of VR, AR and Self-Driving Cars
Study: The Future of VR, AR and Self-Driving CarsStudy: The Future of VR, AR and Self-Driving Cars
Study: The Future of VR, AR and Self-Driving Cars
 

Similar a GeeCON 2013 - EJB application guided by tests

Jersey framework
Jersey frameworkJersey framework
Jersey frameworkknight1128
 
How to Start Test-Driven Development in Legacy Code
How to Start Test-Driven Development in Legacy CodeHow to Start Test-Driven Development in Legacy Code
How to Start Test-Driven Development in Legacy CodeDaniel Wellman
 
Expression trees in c#
Expression trees in c#Expression trees in c#
Expression trees in c#Oleksii Holub
 
Pulsar Architectural Patterns for CI/CD Automation and Self-Service
Pulsar Architectural Patterns for CI/CD Automation and Self-ServicePulsar Architectural Patterns for CI/CD Automation and Self-Service
Pulsar Architectural Patterns for CI/CD Automation and Self-ServiceDevin Bost
 
An Introduction to CSS Preprocessors
An Introduction to CSS PreprocessorsAn Introduction to CSS Preprocessors
An Introduction to CSS PreprocessorsMiloš Sutanovac
 
Presto anatomy
Presto anatomyPresto anatomy
Presto anatomyDongmin Yu
 
10. session 10 loops and arrays
10. session 10   loops and arrays10. session 10   loops and arrays
10. session 10 loops and arraysPhúc Đỗ
 
[245] presto 내부구조 파헤치기
[245] presto 내부구조 파헤치기[245] presto 내부구조 파헤치기
[245] presto 내부구조 파헤치기NAVER D2
 
Advanced QUnit - Front-End JavaScript Unit Testing
Advanced QUnit - Front-End JavaScript Unit TestingAdvanced QUnit - Front-End JavaScript Unit Testing
Advanced QUnit - Front-End JavaScript Unit TestingLars Thorup
 
JavaScript Sprachraum
JavaScript SprachraumJavaScript Sprachraum
JavaScript Sprachraumpatricklee
 
Expression trees in c#, Алексей Голубь (Svitla Systems)
Expression trees in c#, Алексей Голубь (Svitla Systems)Expression trees in c#, Алексей Голубь (Svitla Systems)
Expression trees in c#, Алексей Голубь (Svitla Systems)Alina Vilk
 
PhpUnit Best Practices
PhpUnit Best PracticesPhpUnit Best Practices
PhpUnit Best PracticesEdorian
 
Drupal 8 in action, the route to the method
Drupal 8 in action, the route to the methodDrupal 8 in action, the route to the method
Drupal 8 in action, the route to the methodjuanolalla
 
Orsiso
OrsisoOrsiso
Orsisoe27
 
Arquillian - extensions which you have to take with you to a deserted island
Arquillian - extensions which you have to take with you to a deserted islandArquillian - extensions which you have to take with you to a deserted island
Arquillian - extensions which you have to take with you to a deserted islandSoftwareMill
 
Microservices With Spring Boot and Spring Cloud Netflix
Microservices With Spring Boot and Spring Cloud NetflixMicroservices With Spring Boot and Spring Cloud Netflix
Microservices With Spring Boot and Spring Cloud NetflixKrzysztof Sobkowiak
 

Similar a GeeCON 2013 - EJB application guided by tests (20)

Jersey framework
Jersey frameworkJersey framework
Jersey framework
 
How to Start Test-Driven Development in Legacy Code
How to Start Test-Driven Development in Legacy CodeHow to Start Test-Driven Development in Legacy Code
How to Start Test-Driven Development in Legacy Code
 
Expression trees in c#
Expression trees in c#Expression trees in c#
Expression trees in c#
 
Pulsar Architectural Patterns for CI/CD Automation and Self-Service
Pulsar Architectural Patterns for CI/CD Automation and Self-ServicePulsar Architectural Patterns for CI/CD Automation and Self-Service
Pulsar Architectural Patterns for CI/CD Automation and Self-Service
 
Web Services
Web ServicesWeb Services
Web Services
 
An Introduction to CSS Preprocessors
An Introduction to CSS PreprocessorsAn Introduction to CSS Preprocessors
An Introduction to CSS Preprocessors
 
servlets
servletsservlets
servlets
 
Presto anatomy
Presto anatomyPresto anatomy
Presto anatomy
 
10. session 10 loops and arrays
10. session 10   loops and arrays10. session 10   loops and arrays
10. session 10 loops and arrays
 
[245] presto 내부구조 파헤치기
[245] presto 내부구조 파헤치기[245] presto 내부구조 파헤치기
[245] presto 내부구조 파헤치기
 
Advanced QUnit - Front-End JavaScript Unit Testing
Advanced QUnit - Front-End JavaScript Unit TestingAdvanced QUnit - Front-End JavaScript Unit Testing
Advanced QUnit - Front-End JavaScript Unit Testing
 
JavaScript Sprachraum
JavaScript SprachraumJavaScript Sprachraum
JavaScript Sprachraum
 
Expression trees in c#, Алексей Голубь (Svitla Systems)
Expression trees in c#, Алексей Голубь (Svitla Systems)Expression trees in c#, Алексей Голубь (Svitla Systems)
Expression trees in c#, Алексей Голубь (Svitla Systems)
 
PhpUnit Best Practices
PhpUnit Best PracticesPhpUnit Best Practices
PhpUnit Best Practices
 
Drupal 8 in action, the route to the method
Drupal 8 in action, the route to the methodDrupal 8 in action, the route to the method
Drupal 8 in action, the route to the method
 
Gemless
GemlessGemless
Gemless
 
Orsiso
OrsisoOrsiso
Orsiso
 
Arquillian - extensions which you have to take with you to a deserted island
Arquillian - extensions which you have to take with you to a deserted islandArquillian - extensions which you have to take with you to a deserted island
Arquillian - extensions which you have to take with you to a deserted island
 
Arquillian Extensions
Arquillian ExtensionsArquillian Extensions
Arquillian Extensions
 
Microservices With Spring Boot and Spring Cloud Netflix
Microservices With Spring Boot and Spring Cloud NetflixMicroservices With Spring Boot and Spring Cloud Netflix
Microservices With Spring Boot and Spring Cloud Netflix
 

Más de Jakub Marchwicki

Test with Spock like the first officer
Test with Spock like the first officerTest with Spock like the first officer
Test with Spock like the first officerJakub Marchwicki
 
Design principles 4 hackers - tech3camp (28142014)
Design principles 4 hackers - tech3camp (28142014)Design principles 4 hackers - tech3camp (28142014)
Design principles 4 hackers - tech3camp (28142014)Jakub Marchwicki
 
[PL] Jak programować aby nie zwariować
[PL] Jak programować aby nie zwariować[PL] Jak programować aby nie zwariować
[PL] Jak programować aby nie zwariowaćJakub Marchwicki
 
[PL] Jak programować aby nie zwariować?
[PL] Jak programować aby nie zwariować?[PL] Jak programować aby nie zwariować?
[PL] Jak programować aby nie zwariować?Jakub Marchwicki
 
GeeCON 2012 hurdle run through ejb testing
GeeCON 2012 hurdle run through ejb testingGeeCON 2012 hurdle run through ejb testing
GeeCON 2012 hurdle run through ejb testingJakub Marchwicki
 
[PL] Metadane - dane o danych
[PL] Metadane - dane o danych[PL] Metadane - dane o danych
[PL] Metadane - dane o danychJakub Marchwicki
 
[PL] O klasycznej, programistycznej elegancji
[PL] O klasycznej, programistycznej elegancji[PL] O klasycznej, programistycznej elegancji
[PL] O klasycznej, programistycznej elegancjiJakub Marchwicki
 

Más de Jakub Marchwicki (8)

Test with Spock like the first officer
Test with Spock like the first officerTest with Spock like the first officer
Test with Spock like the first officer
 
Design principles 4 hackers - tech3camp (28142014)
Design principles 4 hackers - tech3camp (28142014)Design principles 4 hackers - tech3camp (28142014)
Design principles 4 hackers - tech3camp (28142014)
 
JEE.next()
JEE.next()JEE.next()
JEE.next()
 
[PL] Jak programować aby nie zwariować
[PL] Jak programować aby nie zwariować[PL] Jak programować aby nie zwariować
[PL] Jak programować aby nie zwariować
 
[PL] Jak programować aby nie zwariować?
[PL] Jak programować aby nie zwariować?[PL] Jak programować aby nie zwariować?
[PL] Jak programować aby nie zwariować?
 
GeeCON 2012 hurdle run through ejb testing
GeeCON 2012 hurdle run through ejb testingGeeCON 2012 hurdle run through ejb testing
GeeCON 2012 hurdle run through ejb testing
 
[PL] Metadane - dane o danych
[PL] Metadane - dane o danych[PL] Metadane - dane o danych
[PL] Metadane - dane o danych
 
[PL] O klasycznej, programistycznej elegancji
[PL] O klasycznej, programistycznej elegancji[PL] O klasycznej, programistycznej elegancji
[PL] O klasycznej, programistycznej elegancji
 

Último

Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsJoaquim Jorge
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?Antenna Manufacturer Coco
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfEnterprise Knowledge
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessPixlogix Infotech
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 

Último (20)

Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 

GeeCON 2013 - EJB application guided by tests

  • 1. EJB applications guided by tests Jakub Marchwicki
  • 8. It started a year ago
  • 11. twitter: @kubem But in fact it started much earlier JBoss 4.x Taking form 7 to 20 minutes to start No CI environment
  • 12. twitter: @kubem Delivery a feature with only a single deploy
  • 13. twitter: @kubem The Good Embedded container Your test is you component Focused integration testing
  • 14. twitter: @kubem INFO - Configuring Service(id=Default Security Service, type=SecurityService, provider-id=Default Security Service) INFO - Configuring Service(id=Default Transaction Manager, type=TransactionManager, provider-id=Default Transaction Manager) INFO - Creating TransactionManager(id=Default Transaction Manager) INFO - Creating SecurityService(id=Default Security Service) INFO - Configuring enterprise application: /home/kubam/workspaces/java/various/jee-examples/stockapp/stockapp-ejb- openejbtest/DozerQuotationConverterIntegrationTest INFO - Auto-deploying ejb DozerConverterCache: EjbDeployment(deployment- id=DozerConverterCache) INFO - Auto-deploying ejb DozerQuotationConverter: EjbDeployment(deployment- id=DozerQuotationConverter) INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default ManagedContainer) INFO - Auto-creating a container for bean pl.marchwicki.jee.stockapp.ejb.DozerQuotationConverterIntegrationTest: Container(type=MANAGED, id=Default Managed Container) INFO - Creating Container(id=Default Managed Container) INFO - Configuring Service(id=Default Security Service, type=SecurityService, provider-id=Default Security Service) INFO - Configuring Service(id=Default Transaction Manager, type=TransactionManager, provider-id=Default Transaction Manager) INFO - Creating TransactionManager(id=Default Transaction Manager) INFO - Creating SecurityService(id=Default Security Service) INFO - Configuring enterprise application: /home/kubam/workspaces/java/various/jee-examples/stockapp/stockapp-ejb- openejbtest/DozerQuotationConverterIntegrationTest INFO - Auto-deploying ejb DozerConverterCache: EjbDeployment(deployment- id=DozerConverterCache) INFO - Auto-deploying ejb DozerQuotationConverter: EjbDeployment(deployment- id=DozerQuotationConverter) INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default ManagedContainer) INFO - Auto-creating a container for bean pl.marchwicki.jee.stockapp.ejb.DozerQuotationConverterIntegrationTest: Container(type=MANAGED, id=Default Managed Container) INFO - Creating Container(id=Default Managed Container)
  • 15. twitter: @kubem @RunWi t h( Appl i cat i onComposer . cl ass) publ i c cl ass Hel l oWorl dServi ceInt egrat i onTest { @EJB Hel l oWor l dSer vi ceLocal hel l oWor l dSer vi ce; @Test publ i c voi d shoul dRet urnHel l o( ) { a s s e r t Eq ua l s ( he l l o Wo r l d Se r v i c e . s a y He l l o ( " Ja kub" ) , " He l l o ! Ja kub" ) ; } / / . . . } @RunWi t h( Appl i cat i onComposer . cl ass) publ i c cl ass Hel l oWorl dServi ceInt egrat i onTest { @EJB Hel l oWor l dSer vi ceLocal hel l oWor l dSer vi ce; @Test publ i c voi d shoul dRet urnHel l o( ) { a s s e r t Eq ua l s ( he l l o Wo r l d Se r v i c e . s a y He l l o ( " Ja kub" ) , " He l l o ! Ja kub" ) ; } / / . . . }
  • 16. twitter: @kubem @RunWi t h( Appl i cat i onComposer . cl ass) publ i c cl ass Audi t MessageRecei verTest { f i nal St ri ng ori gi nal Test Message = "Hel l o Worl d! "; / / . . @Per si st enceCont ext Ent i t yManager em; @Test publ i c voi d processQueue( ) t hrows JMSExcept i on { Li st <Audi t Log> l i st = em. cr eat eQuer y( " f r om Audi t Log" , Audi t Log. cl ass) . get Resul t Li st ( ) ; a s s e r t No t Nul l ( l i s t ) ; a s s e r t Eq ua l s ( 1 , l i s t . s i z e ( ) ) ; a s s e r t Eq ua l s ( o r i g i na l Te s t Me s s a g e , l i s t . g e t ( 0 ) . g e t Me s s a g e ( ) ) ; } / / . . } @RunWi t h( Appl i cat i onComposer . cl ass) publ i c cl ass Audi t MessageRecei verTest { f i nal St ri ng ori gi nal Test Message = "Hel l o Worl d! "; / / . . @Per si st enceCont ext Ent i t yManager em; @Test publ i c voi d processQueue( ) t hrows JMSExcept i on { Li st <Audi t Log> l i st = em. cr eat eQuer y( " f r om Audi t Log" , Audi t Log. cl ass) . get Resul t Li st ( ) ; a s s e r t No t Nul l ( l i s t ) ; a s s e r t Eq ua l s ( 1 , l i s t . s i z e ( ) ) ; a s s e r t Eq ua l s ( o r i g i na l Te s t Me s s a g e , l i s t . g e t ( 0 ) . g e t Me s s a g e ( ) ) ; } / / . . }
  • 17. twitter: @kubem @RunWi t h( Appl i cat i onComposer . cl ass) publ i c cl ass Audi t MessageProcessorTest { @Resour ce( name = " Connect i onFact or y" , mappedName = " Connect i onFact or y" ) Connect i onFact or y connect i onFact or y; @Resour ce( name = " queue/ audi t " , mappedName = " queue/ audi t " ) Queue queue; @Test ( t i meout = 2000) publ i c voi d processQueue( ) t hrows Except i on { f i nal Connect i on connect i on = connect i onFact ory. creat eConnect i on( ) ; connect i on. st ar t ( ) ; f i nal Sessi on sessi on = connect i on. creat eSessi on( f al se, Sessi on. AUTO_ ACKNOWLEDGE) ; f i nal MessageConsumer i ncomi ng = sessi on. creat eConsumer( queue) ; Message r ecei ve = i ncomi ng. r ecei ve( ) ; a s s e r t Tha t ( r e c e i v e , new IsInst anceOf (Text Message. cl ass)); a s s e r t Eq ua l s ( o r i g i na l Te s t Me s s a g e , ( ( Te x t Me s s a g e ) r e c e i v e ) . g e t Te x t ( ) ) ; } / / . . . } @RunWi t h( Appl i cat i onComposer . cl ass) publ i c cl ass Audi t MessageProcessorTest { @Resour ce( name = " Connect i onFact or y" , mappedName = " Connect i onFact or y" ) Connect i onFact or y connect i onFact or y; @Resour ce( name = " queue/ audi t " , mappedName = " queue/ audi t " ) Queue queue; @Test ( t i meout = 2000) publ i c voi d processQueue( ) t hrows Except i on { f i nal Connect i on connect i on = connect i onFact ory. creat eConnect i on( ) ; connect i on. st ar t ( ) ; f i nal Sessi on sessi on = connect i on. creat eSessi on( f al se, Sessi on. AUTO_ ACKNOWLEDGE) ; f i nal MessageConsumer i ncomi ng = sessi on. creat eConsumer( queue) ; Message r ecei ve = i ncomi ng. r ecei ve( ) ; a s s e r t Tha t ( r e c e i v e , new IsInst anceOf (Text Message. cl ass)); a s s e r t Eq ua l s ( o r i g i na l Te s t Me s s a g e , ( ( Te x t Me s s a g e ) r e c e i v e ) . g e t Te x t ( ) ) ; } / / . . . }
  • 18. twitter: @kubem @RunWi t h( Appl i cat i onComposer . cl ass) publ i c cl ass Hel l oWorl dServi ceInt egrat i onTest { @Test publ i c voi d shoul dCal l WebServi ce( ) t hrows Except i on { URL wsdl Document Locat i on = new URL( "ht t p: //127. 0. 0. 1: 4204/modul e/Hel l oWorl dServi ce? wsdl ") ; St r i ng namespaceURI = " ht t p: / / hw. ej b. st ockapp. j ee. mar chwi cki . pl / " ; St r i ng ser vi cePar t = " Hel l oWor l dSer vi ceSer vi ce" ; QName ser vi ceQN = new QName( namespaceURI, servi cePart ) ; Ser vi ce ser vi ce = Ser vi ce. c r e a t e ( ws d l Do c ume nt Lo c a t i o n, s e r v i c e QN) ; Hel l oWor l dSer vi ceLocal hel l oWor l d = ser vi ce. get Por t ( Hel l oWor l dSer vi ceLocal . cl ass) ; St r i ng s = hel l oWor l d. sayHel l o( " Jakub" ) ; a s s e r t Eq ua l s ( " He l l o ! Ja kub" , s ) ; } / / . . . } @RunWi t h( Appl i cat i onComposer . cl ass) publ i c cl ass Hel l oWorl dServi ceInt egrat i onTest { @Test publ i c voi d shoul dCal l WebServi ce( ) t hrows Except i on { URL wsdl Document Locat i on = new URL( "ht t p: //127. 0. 0. 1: 4204/modul e/Hel l oWorl dServi ce? wsdl ") ; St r i ng namespaceURI = " ht t p: / / hw. ej b. st ockapp. j ee. mar chwi cki . pl / " ; St r i ng ser vi cePar t = " Hel l oWor l dSer vi ceSer vi ce" ; QName ser vi ceQN = new QName( namespaceURI, servi cePart ) ; Ser vi ce ser vi ce = Ser vi ce. c r e a t e ( ws d l Do c ume nt Lo c a t i o n, s e r v i c e QN) ; Hel l oWor l dSer vi ceLocal hel l oWor l d = ser vi ce. get Por t ( Hel l oWor l dSer vi ceLocal . cl ass) ; St r i ng s = hel l oWor l d. sayHel l o( " Jakub" ) ; a s s e r t Eq ua l s ( " He l l o ! Ja kub" , s ) ; } / / . . . }
  • 19. twitter: @kubem The Bad Differences between containers Vagueness of the EJB spec No test with the actual server
  • 20. twitter: @kubem JNDI tree • {deploymentId} / {interfaceClass} • {appName} / {moduleName} / {beanName} But where it’s localted? • java: app/* • java: comp/env/* • java: global/*
  • 21. twitter: @kubem Multiple names publ i c i nt erf ace Servi ce { publ i c St ri ng hel l o( ) ; } publ i c i nt erf ace Servi ce { publ i c St ri ng hel l o( ) ; }
  • 22. twitter: @kubem Multiple names publ i c i nt erf ace Servi ce { publ i c St ri ng hel l o( ) ; } publ i c i nt erf ace Servi ce { publ i c St ri ng hel l o( ) ; } @St at el ess publ i c cl ass MyServi ce i mpl ement s Servi ce { publ i c St ri ng hel l o( ) { ret urn "Hel l o worl d! "; } } @St at el ess publ i c cl ass MyServi ce i mpl ement s Servi ce { publ i c St ri ng hel l o( ) { ret urn "Hel l o worl d! "; } }
  • 23. twitter: @kubem Multiple names publ i c i nt erf ace Servi ce { publ i c St ri ng hel l o( ) ; } publ i c i nt erf ace Servi ce { publ i c St ri ng hel l o( ) ; } @St at el ess publ i c cl ass MyServi ce i mpl ement s Servi ce { publ i c St ri ng hel l o( ) { ret urn "Hel l o worl d! "; } } @St at el ess publ i c cl ass MyServi ce i mpl ement s Servi ce { publ i c St ri ng hel l o( ) { ret urn "Hel l o worl d! "; } } @St at el ess publ i c cl ass MyOt herServi ce i mpl ement s Servi ce { publ i c St ri ng hel l o( ) { ret urn "Hel l o GeeCON! "; } } @St at el ess publ i c cl ass MyOt herServi ce i mpl ement s Servi ce { publ i c St ri ng hel l o( ) { ret urn "Hel l o GeeCON! "; } }
  • 24. twitter: @kubem Multiple names publ i c i nt erf ace Servi ce { publ i c St ri ng hel l o( ) ; } publ i c i nt erf ace Servi ce { publ i c St ri ng hel l o( ) ; } @St at el ess publ i c cl ass MyServi ce i mpl ement s Servi ce { publ i c St ri ng hel l o( ) { ret urn "Hel l o worl d! "; } } @St at el ess publ i c cl ass MyServi ce i mpl ement s Servi ce { publ i c St ri ng hel l o( ) { ret urn "Hel l o worl d! "; } } @St at el ess publ i c cl ass MyOt herServi ce i mpl ement s Servi ce { publ i c St ri ng hel l o( ) { ret urn "Hel l o GeeCON! "; } } @St at el ess publ i c cl ass MyOt herServi ce i mpl ement s Servi ce { publ i c St ri ng hel l o( ) { ret urn "Hel l o GeeCON! "; } } @St ar t up @Si ngl et on publ i c cl ass Cl i ent { @EJB Ser vi ce ser vi ce; @Post Const r uct publ i c voi d i ni t ( ) { Syst em. o ut . p r i nt l n( s e r v i c e . he l l o ( ) ) ; } } @St ar t up @Si ngl et on publ i c cl ass Cl i ent { @EJB Ser vi ce ser vi ce; @Post Const r uct publ i c voi d i ni t ( ) { Syst em. o ut . p r i nt l n( s e r v i c e . he l l o ( ) ) ; } }
  • 25. twitter: @kubem DEPLOYMENTS IN ERROR: Deployment "vfs:///opt/java/jboss- 6.1.0.Final/server/default/deploy/module.jar" is in error due to the following reason(s): java.lang.RuntimeException: Specified reference [EJB Reference: beanInterface 'pl.marchwicki.jee6.Service', beanName 'null', mappedName 'null', lookupName 'null', owning unit 'ComponentDeploymentContext@2078856098{org.jboss.metadata.ejb.jboss.JBo ssEnterpriseBeanMetaData.Client}'] was matched by more than one EJB: [org.jboss.metadata.ejb.jboss.JBossSessionBean31MetaData@8b7ff749{MySer vice}, org.jboss.metadata.ejb.jboss.JBossSessionBean31MetaData@5baed971{MyOthe rService}]. Specify beanName explciitly or ensure beanInterface is unique. DEPLOYMENTS IN ERROR: Deployment "vfs:///opt/java/jboss- 6.1.0.Final/server/default/deploy/module.jar" is in error due to the following reason(s): java.lang.RuntimeException: Specified reference [EJB Reference: beanInterface 'pl.marchwicki.jee6.Service', beanName 'null', mappedName 'null', lookupName 'null', owning unit 'ComponentDeploymentContext@2078856098{org.jboss.metadata.ejb.jboss.JBo ssEnterpriseBeanMetaData.Client}'] was matched by more than one EJB: [org.jboss.metadata.ejb.jboss.JBossSessionBean31MetaData@8b7ff749{MySer vice}, org.jboss.metadata.ejb.jboss.JBossSessionBean31MetaData@5baed971{MyOthe rService}]. Specify beanName explciitly or ensure beanInterface is unique.
  • 26. twitter: @kubem INFO: Created Ejb(deployment-id=Client, ejb-name=Client, container=My Singleton Container) May 11, 013 4:23:24 PM org.apache.openejb.assembler.classic.Assembler startEjbs INFO: Started Ejb(deployment-id=MyService, ejb-name=MyService, container=My Stateless Container) May 11, 2013 4:23:24 PM org.apache.openejb.assembler.classic.Assembler startEjbs INFO: Started Ejb(deployment-id=MyOtherService, ejb-name=MyOtherService, container=My Stateless Container) Hello world! INFO: Created Ejb(deployment-id=Client, ejb-name=Client, container=My Singleton Container) May 11, 013 4:23:24 PM org.apache.openejb.assembler.classic.Assembler startEjbs INFO: Started Ejb(deployment-id=MyService, ejb-name=MyService, container=My Stateless Container) May 11, 2013 4:23:24 PM org.apache.openejb.assembler.classic.Assembler startEjbs INFO: Started Ejb(deployment-id=MyOtherService, ejb-name=MyOtherService, container=My Stateless Container) Hello world!
  • 27. twitter: @kubem Different implementations @Xml Root El ement publ i c cl ass Todo { pri vat e l ong i d; @Not Nul l @Si ze( mi n = 1) pri vat e St ri ng t i t l e; pri vat e l ong order; pri vat e bool ean compl et ed; / / . . . } @Xml Root El ement publ i c cl ass Todo { pri vat e l ong i d; @Not Nul l @Si ze( mi n = 1) pri vat e St ri ng t i t l e; pri vat e l ong order; pri vat e bool ean compl et ed; / / . . . }
  • 28. twitter: @kubem Different implementations @Xml Root El ement publ i c cl ass Todo { pri vat e l ong i d; @Not Nul l @Si ze( mi n = 1) pri vat e St ri ng t i t l e; pri vat e l ong order; pri vat e bool ean compl et ed; / / . . . } @Xml Root El ement publ i c cl ass Todo { pri vat e l ong i d; @Not Nul l @Si ze( mi n = 1) pri vat e St ri ng t i t l e; pri vat e l ong order; pri vat e bool ean compl et ed; / / . . . } @Pat h( " / t odos" ) @Pr oduces( Medi aType. APPLICATION_ JSON) publ i c cl ass TodoResource { @GET publ i c Li st <Todo> get Al l ( ) { ret urn st ore. get Al l ( ) ; } @GET @Pat h( " / { i d} " ) publ i c Todo get ( @Pat hParam( "i d") l ong i d) { ret urn st ore. get ( i d) ; } / / . . . } @Pat h( " / t odos" ) @Pr oduces( Medi aType. APPLICATION_ JSON) publ i c cl ass TodoResource { @GET publ i c Li st <Todo> get Al l ( ) { ret urn st ore. get Al l ( ) ; } @GET @Pat h( " / { i d} " ) publ i c Todo get ( @Pat hParam( "i d") l ong i d) { ret urn st ore. get ( i d) ; } / / . . . }
  • 29. twitter: @kubem GET /todos/1 HTTP/1.1 Host: localhost HTTP/1.1 200 OK { "id": 1, "title": "First todo", "order": 1, "completed": false } GET /todos/1 HTTP/1.1 Host: localhost HTTP/1.1 200 OK { "id": 1, "title": "First todo", "order": 1, "completed": false } GET /todos HTTP/1.1 Host: localhost HTTP/1.1 200 OK [ { "id": 1, "title": "First todo", "order": 1, "completed": false }, { "id": 2, "title": "Second todo", "order": 2, "completed": false } ] GET /todos HTTP/1.1 Host: localhost HTTP/1.1 200 OK [ { "id": 1, "title": "First todo", "order": 1, "completed": false }, { "id": 2, "title": "Second todo", "order": 2, "completed": false } ]
  • 30. twitter: @kubem GET /todos/1 HTTP/1.1 Host: localhost HTTP/1.1 200 OK { todo: { "id": 1, "title": "First todo", "order": 1, "completed": false } } GET /todos/1 HTTP/1.1 Host: localhost HTTP/1.1 200 OK { todo: { "id": 1, "title": "First todo", "order": 1, "completed": false } } GET /todos HTTP/1.1 Host: localhost HTTP/1.1 200 OK { todo: [ { "id": 1, "title": "First todo", "order": 1, "completed": false }, { "id": 2, "title": "Second todo", "order": 2, "completed": false } ] } GET /todos HTTP/1.1 Host: localhost HTTP/1.1 200 OK { todo: [ { "id": 1, "title": "First todo", "order": 1, "completed": false }, { "id": 2, "title": "Second todo", "order": 2, "completed": false } ] }
  • 31. twitter: @kubem GET /todos/1 HTTP/1.1 Host: localhost HTTP/1.1 200 OK { todo: { "id": 1, "title": "First todo", "order": 1, "completed": false } } GET /todos/1 HTTP/1.1 Host: localhost HTTP/1.1 200 OK { todo: { "id": 1, "title": "First todo", "order": 1, "completed": false } } GET /todos HTTP/1.1 Host: localhost HTTP/1.1 200 OK { todo: [ { "id": 1, "title": "First todo", "order": 1, "completed": false }, { "id": 2, "title": "Second todo", "order": 2, "completed": false } ] } GET /todos HTTP/1.1 Host: localhost HTTP/1.1 200 OK { todo: [ { "id": 1, "title": "First todo", "order": 1, "completed": false }, { "id": 2, "title": "Second todo", "order": 2, "completed": false } ] }
  • 32. twitter: @kubem The Ugly Loads of boilerplate code Tests only EJBs Never deployed
  • 33. twitter: @kubem @RunWi t h( Appl i cat i onComposer . cl ass) publ i c cl ass Audi t MessageRecei verTest { f i nal St ri ng ori gi nal Test Message = "Hel l o Worl d! "; //. . @Per si st enceCont ext Ent i t yManager em; @Test publ i c voi d processQueue( ) t hrows JMSExcept i on { Li st <Audi t Log> l i st = em. cr eat eQuer y( " f r om Audi t Log" , Audi t Log. cl ass) . get Resul t Li st ( ) ; a s s e r t No t Nul l ( l i s t ) ; a s s e r t Eq ua l s ( 1 , l i s t . s i z e ( ) ) ; a s s e r t Eq ua l s ( o r i g i na l Te s t Me s s a g e , l i s t . g e t ( 0 ) . g e t Me s s a g e ( ) ) ; } //. . } @RunWi t h( Appl i cat i onComposer . cl ass) publ i c cl ass Audi t MessageRecei verTest { f i nal St ri ng ori gi nal Test Message = "Hel l o Worl d! "; //. . @Per si st enceCont ext Ent i t yManager em; @Test publ i c voi d processQueue( ) t hrows JMSExcept i on { Li st <Audi t Log> l i st = em. cr eat eQuer y( " f r om Audi t Log" , Audi t Log. cl ass) . get Resul t Li st ( ) ; a s s e r t No t Nul l ( l i s t ) ; a s s e r t Eq ua l s ( 1 , l i s t . s i z e ( ) ) ; a s s e r t Eq ua l s ( o r i g i na l Te s t Me s s a g e , l i s t . g e t ( 0 ) . g e t Me s s a g e ( ) ) ; } //. . } Configuration
  • 34. twitter: @kubem @RunWi t h( Appl i cat i onComposer . cl ass) publ i c cl ass Audi t MessageRecei verTest { @Modul e publ i c Ej bJar modul e( ) { f i nal Ej bJar ej bJar = new Ej bJar( ) ; ej bJar . addEnt er pr i seBean( new St at el essBean( Audi t MessageProcessi ng. cl ass) ) ; ej bJar . addEnt er pr i seBean( new St at el essBean( Audi t LoggerServi ce. cl ass) ) ; ej bJar . addEnt er pr i seBean( new MessageDri venBean( Audi t i ngMessageLi st erner. cl ass) ) ; ret urn ej bJar; } //. . @RunWi t h( Appl i cat i onComposer . cl ass) publ i c cl ass Audi t MessageRecei verTest { @Modul e publ i c Ej bJar modul e( ) { f i nal Ej bJar ej bJar = new Ej bJar( ) ; ej bJar . addEnt er pr i seBean( new St at el essBean( Audi t MessageProcessi ng. cl ass) ) ; ej bJar . addEnt er pr i seBean( new St at el essBean( Audi t LoggerServi ce. cl ass) ) ; ej bJar . addEnt er pr i seBean( new MessageDri venBean( Audi t i ngMessageLi st erner. cl ass) ) ; ret urn ej bJar; } //. .
  • 35. twitter: @kubem @RunWi t h( Appl i cat i onComposer . cl ass) publ i c cl ass Audi t MessageRecei verTest { //. . @Modul e publ i c Persi st enceUni t persi st ence( ) { Per si st enceUni t uni t = new Persi st enceUni t ( "st ockapp- audi t ") ; uni t . set Jt aDat aSour ce( " Def aul t DS" ) ; uni t . set Pr ovi der ( Hi ber nat ePer si st ence. cl ass) ; uni t . addCl ass( Audi t Log. cl ass) ; Pr oper t i es dbPr oper t i es = new Propert i es( ) ; dbPr oper t i es. set Pr oper t y( " hi ber nat e. hbm2ddl . aut o" , " cr eat e- dr op" ) ; dbPr oper t i es. set Pr oper t y( " hi ber nat e. di al ect " , " or g. hi ber nat e. di al ect . HSQLDi al ect " ) ; dbPr oper t i es. set Pr oper t y" hi ber nat e. use_sql _comment s" , " t r ue" ) ; dbPr oper t i es. set Pr oper t y( " hi ber nat e. show_sql " , " t r ue" ) ; dbPr oper t i es. set Pr oper t y( " hi ber nat e. f or mat _sql " , " t r ue" ) ; uni t . set Pr oper t i es( dbPr oper t i es) ; ret urn uni t ; } //. . @RunWi t h( Appl i cat i onComposer . cl ass) publ i c cl ass Audi t MessageRecei verTest { //. . @Modul e publ i c Persi st enceUni t persi st ence( ) { Per si st enceUni t uni t = new Persi st enceUni t ( "st ockapp- audi t ") ; uni t . set Jt aDat aSour ce( " Def aul t DS" ) ; uni t . set Pr ovi der ( Hi ber nat ePer si st ence. cl ass) ; uni t . addCl ass( Audi t Log. cl ass) ; Pr oper t i es dbPr oper t i es = new Propert i es( ) ; dbPr oper t i es. set Pr oper t y( " hi ber nat e. hbm2ddl . aut o" , " cr eat e- dr op" ) ; dbPr oper t i es. set Pr oper t y( " hi ber nat e. di al ect " , " or g. hi ber nat e. di al ect . HSQLDi al ect " ) ; dbPr oper t i es. set Pr oper t y" hi ber nat e. use_sql _comment s" , " t r ue" ) ; dbPr oper t i es. set Pr oper t y( " hi ber nat e. show_sql " , " t r ue" ) ; dbPr oper t i es. set Pr oper t y( " hi ber nat e. f or mat _sql " , " t r ue" ) ; uni t . set Pr oper t i es( dbPr oper t i es) ; ret urn uni t ; } //. .
  • 36. twitter: @kubem @RunWi t h( Appl i cat i onComposer . cl ass) publ i c cl ass Audi t MessageRecei verTest { //. . @Conf i gur at i on publ i c Propert i es conf i g( ) t hrows Except i on { Pr oper t i es p = new Propert i es( ) ; p. put ( " Def aul t DS" , " new: / / Resour ce?t ype=Dat aSour ce" ) ; p. put ( " Def aul t DS. JdbcDr i ver " , " or g. hsql db. j dbcDr i ver " ) ; p. put ( " Def aul t DS. JdbcUr l " , " j dbc: hsql db: mem: t est db" ) ; ret urn p; } //. . @RunWi t h( Appl i cat i onComposer . cl ass) publ i c cl ass Audi t MessageRecei verTest { //. . @Conf i gur at i on publ i c Propert i es conf i g( ) t hrows Except i on { Pr oper t i es p = new Propert i es( ) ; p. put ( " Def aul t DS" , " new: / / Resour ce?t ype=Dat aSour ce" ) ; p. put ( " Def aul t DS. JdbcDr i ver " , " or g. hsql db. j dbcDr i ver " ) ; p. put ( " Def aul t DS. JdbcUr l " , " j dbc: hsql db: mem: t est db" ) ; ret urn p; } //. .
  • 37. twitter: @kubem Test only EJB It’s not a real application server Webservices: Apache CXF JMS: Apache MQ JPA: OpenJPA Hibernate (any provider)
  • 38. Where we are now?
  • 39. twitter: @kubem The aliens have landed • Arquillian is a testing framework • There are runners… • Containers… • & Enrichers
  • 40. twitter: @kubem The aliens have landed • Arquillian is a testing framework • There are runners… – JUnit – TestNG • Containers… • & Enrichers
  • 41. twitter: @kubem The aliens have landed • Arquillian is a testing framework • There are runners… • Containers… – Weld – Tomcat – JBoss – Glassfish • & Enrichers
  • 42. twitter: @kubem The aliens have landed • Arquillian is a testing framework • There are runners… • Containers… • & Enrichers – glue layer between your code and the container: inject, track results
  • 44. twitter: @kubem The are three modes • Embedded – You run your app server together with your code, in a single JVM • Managed – Arquillian starts and stops your nodes, together with an app, in separate JVMs • Remote – Everything is remotly deployed
  • 45. twitter: @kubem And four ways for communicating results • Local – Same JVM, local bindings • Servlet 2.5 – Pre JEE-6 containers • Servlet 3.0 – Leveraging async servlets • JMX – Jboss AS 7 way
  • 46. How it works in practice
  • 47. twitter: @kubem Why we do it? • Real test with real services (no mocks movement) • With real environment • Short feedback cycle
  • 48. twitter: @kubem What’s next • Persitence Extension (DBUnit) • GWT Extension • JSFUnit • BPEL testing • Performance • … ?
  • 49. twitter: @kubem Call for arms Arquillian Test Porting Initiative
  • 51. twitter: @kubem Projects to tackle • Active MQ • Apache CXF • TomEE & OpenEJB • MyFaces • OpenWenBeans • BVal
  • 53. twitter: @kubem You can innovate on nonfunctional areas, such as devops, logging, metrics, etc, if your core business needs to be more conservative.
  • 54. twitter: @kubem Innovation comes not just from using new technologies, but also from using new techniques with old boring technologies

Notas del editor

  1. It all started with OpenEJB – and that was the driver for last year talk. Much have changed since than – year is like an epoch, but lets recap
  2. And that way I started digging embeddable containters. OpenEJB was the only option. We started with classpath scanning. We built a test. Run. Scan everything and got a result… or not ;-) So the test sometimes worked, sometimes didnt
  3. It was possible to bootstrap the container Your test class was as EJB component – injections were possible Different granularity of test were possible (not only unit as in unit and not only end-2-end) Testing the border between application and the application server (configuration elements).
  4. So we have an actual container
  5. Our tests are EJB components
  6. We can test certain slices within the container
  7. Including JMS
  8. And web services
  9. OpenEJB is eventually one of many spec implementation – not necessary the one you use at production The spec is vague – and there are many little but important differences (duplicate names) Everything is run within a single JVM The spec is a set of libraries, components – implementations differs. Apache CXF and RestEASY (jettison and jackson)
  10. I’ll not talk about non standard extensions (like additional annotations in Hibernate – that’s failry obvious). But take this example
  11. I’ll not talk about non standard extensions (like additional annotations in Hibernate – that’s failry obvious). But take this example
  12. This happens just by changing implementation from jackson (default on RestEASY and Jboss) to jettison (default on Apache CXF hence TomEE). From the application (front end perspective) it’s a huge difference.
  13. Building and configuring the application (the deployment) was cumbersome If focus only on EJB the differences were minimal, magic happened when you started to test web services Your code never actually got deployed (similar to Spring Test) – it have never been tested against the actual application server: Tomcat, Jboss etc
  14. We can test certain slices within the container
  15. We can test certain slices within the container
  16. We can test certain slices within the container
  17. We can test certain slices within the container
  18. What happened since then * Arquillian matured * ApplicationComposer is still alive – but it’s not the main driver * OpenEJB evolved into TomEE (which just become 1.5.2) * Arquillian become main driver for OpenSourced TCK
  19. Arquillian abstract container or application startup logic away from your tests (that bit we had for openEJB) Allows to deploy your application to targeted runtime (embedded, managed)
  20. The JVM bit is very important
  21. The JVM bit is very important