Top Banner
MAKING JAVA WEB-APPS GROOVY GROOVY FOR FUN AND PLEASURE. by Franjo Ž ili ć
26

Javantura v2 - Making Java web-apps Groovy - Franjo Žilić

Jul 05, 2015

Download

Technology

How can you get more done by doing less? Can Spring Web MVC applications look simpler? How can writing less code mean more? How can using Groovy in JUnit tests speed up writing tests. Making data driven tests cool with Spock. All in existing living Java web applications with sample code in Java and Groovy.
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Javantura v2 - Making Java web-apps Groovy - Franjo Žilić

MAKING JAVA WEB-APPSGROOVY

GROOVY FOR FUN AND PLEASURE.by Franjo Žilić

Page 2: Javantura v2 - Making Java web-apps Groovy - Franjo Žilić

TODAYGroovy vs. Java

Spring with Groovy

Testing with Groovy

More testing with Groovy

Page 3: Javantura v2 - Making Java web-apps Groovy - Franjo Žilić

http://groovy.codehaus.org

Groovy is a dynamic language of JVM which adds features towell known Java syntax and JDK libraries inspired by languages

like Python, Ruby, Smalltalk.

Page 4: Javantura v2 - Making Java web-apps Groovy - Franjo Žilić

...Makes Java code simpler and easier to read.

Interoperable with Java libraries.

Compiles into Java bytecode.

Let's you get more done by doing less.

Types are optional or checked.

Page 5: Javantura v2 - Making Java web-apps Groovy - Franjo Žilić

SOME DIFFERENCESdefault importssemicolons are optionalreturn is optional== means .equalsgetters and setters appear on their ownpublic by defaulttruth is not what it wasparentheses are optional * but we like them

Page 6: Javantura v2 - Making Java web-apps Groovy - Franjo Žilić

REAL TIME SAVERSiteration methodsoperators

null safe dereference - ?.elvis - ?:spread - *.regex - =~ ==~subscript - b[0]

Page 7: Javantura v2 - Making Java web-apps Groovy - Franjo Žilić

WHY GROOVY IN WEB APP?Thought before syntax.

Easy to learn *if we know Java

Less code - fewer errors.

Less code - more tests.

Page 8: Javantura v2 - Making Java web-apps Groovy - Franjo Žilić

WHY NOT GRAILS

Rewriting takes time.

Taking small steps.

Whole new ecosystem?

Being forced?

Page 9: Javantura v2 - Making Java web-apps Groovy - Franjo Žilić

INTEGRATIONAnt

Maven

Gradle

Page 10: Javantura v2 - Making Java web-apps Groovy - Franjo Žilić

ANTNative groovyc integration

Supports any Groovy version

Uses stubs for joint (Java+Groovy) projects

... uses ant

Page 11: Javantura v2 - Making Java web-apps Groovy - Franjo Žilić

MAVEN

GMAVENPLUSSupports any Groovy version

Not a native maven-compiler plugin

Poor IDE integration (Eclipse)

Uses stubs...

Page 12: Javantura v2 - Making Java web-apps Groovy - Franjo Žilić

MAVEN

GROOVY ECLIPSE COMPILERNative maven-compiler-plugin

Good IDE integration (Eclipse, IntelliJ)

Restricts Groovy version

No support for invoke-dynamic

Page 13: Javantura v2 - Making Java web-apps Groovy - Franjo Žilić

GRADLEUses groovyc ant task, so applies as for ant

Decent IDE integration

Page 14: Javantura v2 - Making Java web-apps Groovy - Franjo Žilić

SAVING TIME IN PRODUCTION CODELet's say we have a model

... we can't change it

... we get a list of UglyJavaModel objects

... anything can be null

Page 15: Javantura v2 - Making Java web-apps Groovy - Franjo Žilić

REQUIREMENTSsomeone said:

count with theAllImportantBoolean truetop three sorted by someMonetaryValue descending

Page 16: Javantura v2 - Making Java web-apps Groovy - Franjo Žilić

JAVALet's just count those they want

final List<UglyJavaModel> list = thirdPartyService.onlyWayToGetData();

int countOfThoseWithBooleanTrue = 0;

for (final UglyJavaModel uglyJavaModel : list) { if (uglyJavaModel.getNested() != null && uglyJavaModel.getNested().getNested() != null && uglyJavaModel.getNested().getNested().getNested() != null && uglyJavaModel.getNested().getNested().getNested() .getTheAllImportantBoolean() == true) {

countOfThoseWithBooleanTrue++; }}model.addAttribute("countWithBooleanTrue", countOfThoseWithBooleanTrue);

Java can do better, but...

Page 17: Javantura v2 - Making Java web-apps Groovy - Franjo Žilić

JAVAAnd just top three

final List<UglyJavaModel> list = thirdPartyService.onlyWayToGetData();

list.sort(new Comparator<UglyJavaModel>() { @Override public int compare(final UglyJavaModel left, final UglyJavaModel right) { return left.getNested().getSomeMonetaryValue() .compareTo(right.getNested().getSomeMonetaryValue()) * -1; }});

final List<String> topThree = new ArrayList<String>(3);for (final UglyJavaModel uglyJavaModel : list.subList(0, 3)) { topThree.add(uglyJavaModel.getSomeName());}model.addAttribute("topThree", topThree);

Page 18: Javantura v2 - Making Java web-apps Groovy - Franjo Žilić

GROOVYI know, this is boring

def list = thirdPartyService.onlyWayToGetData()

model.addAttribute("countWithBooleanTrue", list.count { it?.nested?.nested?.nested?.theAllImportantBoolean})

model.addAttribute("topThree", list.sort { a, b -> b.nested.someMonetaryValue <=> a.nested.someMonetaryValue}[0..2]*.someName)

Page 19: Javantura v2 - Making Java web-apps Groovy - Franjo Žilić

TESTINGJUnit is good enough

... but we still have to write a lot of code

... and we need a lot of libraries

Page 20: Javantura v2 - Making Java web-apps Groovy - Franjo Žilić

WHY GROOVYsimpler asserts

dynamic groovy

less code

Page 21: Javantura v2 - Making Java web-apps Groovy - Franjo Žilić

CLASSIC JUNIT4 TEST @RunWith(MockitoJUnitRunner.class) //omitted imports - Mockito, Assertionspublic class TipicalJunitTest { @Test //ommited mocks and prepare data public void testUglyJavaControllerReturingCorrectCount() { final UglyJavaController controller = new UglyJavaController(service); final ArrayList<UglyJavaModel> uglyJavaModels = prepareData(); when(service.onlyWayToGetData()).thenReturn(uglyJavaModels); final String view = controller.showSomething(model); assertThat(view).isEqualTo("ugly"); verify(model).addAttribute(eq("countWithBooleanTrue"), eq(1)); verify(model).addAttribute(eq("topThree"), captor.capture()); verify(service).onlyWayToGetData(); verifyNoMoreInteractions(service, model); assertThat(captor.getValue()).containsExactly("first","third","second"); }}

Page 22: Javantura v2 - Making Java web-apps Groovy - Franjo Žilić

SAME TEST, GROOVY WAY class GroovyJunitTest { def data = [/* prepare data*/] // use mocks if you want @Test void testUglyJavaControllerReturingCorrectCount() { def controller = new UglyJavaController([onlyWayToGetData: { return data }] as ThirdPartyService) assert controller.showSomething([addAttribute: { String attr, value -> if (attr == 'countWithBooleanTrue') { assert value == 1 } else if (attr == 'topThree') { assert value == ['first', 'third', 'second'] } else { assert false } }] as Model) == 'ugly' }}

Page 23: Javantura v2 - Making Java web-apps Groovy - Franjo Žilić

DATA DRIVEN TESTS... the dreaded Parameterized runner

What about data driven with Spring context?

No out of the box solution.

Page 24: Javantura v2 - Making Java web-apps Groovy - Franjo Žilić

WELCOME SPOCK... an expressive testing and specification framework

brings new meaning to data driven

Written in Groovy, inspired by others*, compatible with JUnit*JUnit, jMock, Mockito, RSpec...

Page 25: Javantura v2 - Making Java web-apps Groovy - Franjo Žilić

@ContextConfiguration(['classpath:spring/test-config.xml'])class SneakPeekSpockSpecification extends Specification { @Autowired SimpleSpringService service

@Unroll void "just a simple sneak peak for spock"() { given: def testService = new SpockDemoService(service) expect: "dependencies are met" service

when: "calculate average for #booleanValue #givenValues.inspect()" def average = testService.averageValueFor(booleanValue, givenValues.collect { return new UglyJavaModel(nested: new UglyJavaModelNested(someMonetaryValue: it.d, nested: new UglyJavaModelNestedNested(nested: new UglyJavaModelNestedNestedNested(theAllImportantBoolean: it.b)))) })

then: "average value should be #expected" average == expected

where: booleanValue|givenValues || expected true |[[b:true,d:42.98],[b:false,d:4.3],[b:true,d:27.31]]||35.14 false |[[b:true,d:42.98],[b:false,d:4.3],[b:true,d:27.31]]||4.3 true |[[b:true,d:42.98],[b:true,d:4.3],[b:true,d:27.31]] ||24.86 }}

Page 26: Javantura v2 - Making Java web-apps Groovy - Franjo Žilić

https://github.com/fzilic/making-java-groovy

QUESTIONS?