keep your wicket application in production

47
Martijn Dashorst Topicus ...and keep your weekends free Get your application in production...

Upload: martijn-dashorst

Post on 24-May-2015

5.658 views

Category:

Business


4 download

TRANSCRIPT

Page 1: Keep your Wicket application in production

Martijn DashorstTopicus

...and keep your weekends free

Get your applicationin production...

Page 2: Keep your Wicket application in production

6 WAYS TO KEEP YOUR JOB OUT OF YOUR WEEKEND

Page 3: Keep your Wicket application in production

1. USE WICKET TESTER

Page 4: Keep your Wicket application in production

WICKETTESTER

• Test components directly, or their markup

• Runs tests without starting server

• Ajax testing (server side)

• Runs in IDE, ant, maven builds

• Achieves high code coverage

Page 5: Keep your Wicket application in production

HELLOWORLD TEST

@Test public void labelContainsHelloWorld() { }

Page 6: Keep your Wicket application in production

HELLOWORLD TEST

@Test public void labelContainsHelloWorld() { WicketTester tester = new WicketTester(); }

Page 7: Keep your Wicket application in production

HELLOWORLD TEST

@Test public void labelContainsHelloWorld() { WicketTester tester = new WicketTester(); tester.startPage(HelloWorld.class); }

Page 8: Keep your Wicket application in production

HELLOWORLD TEST

@Test public void labelContainsHelloWorld() { WicketTester tester = new WicketTester(); tester.startPage(HelloWorld.class); tester.assertLabel("message", "Hello, World!"); }

Page 9: Keep your Wicket application in production

LINK TEST

@Test public void countingLinkClickTest() { }

Page 10: Keep your Wicket application in production

LINK TEST

@Test public void countingLinkClickTest() { WicketTester tester = new WicketTester(); }

Page 11: Keep your Wicket application in production

LINK TEST

@Test public void countingLinkClickTest() { WicketTester tester = new WicketTester(); tester.startPage(LinkCounter.class); }

Page 12: Keep your Wicket application in production

LINK TEST

@Test public void countingLinkClickTest() { WicketTester tester = new WicketTester(); tester.startPage(LinkCounter.class); tester.assertModelValue("label", 0); }

Page 13: Keep your Wicket application in production

LINK TEST

@Test public void countingLinkClickTest() { WicketTester tester = new WicketTester(); tester.startPage(LinkCounter.class); tester.assertModelValue("label", 0); tester.clickLink("link");}

Page 14: Keep your Wicket application in production

LINK TEST

@Testpublic void countingLinkClickTest() { WicketTester tester = new WicketTester(); tester.startPage(LinkCounter.class); tester.assertModelValue("label", 0); tester.clickLink("link"); tester.assertModelValue("label", 1);}

Page 15: Keep your Wicket application in production

NAVIGATION TEST

@Testpublic void navigateToSecondPage() {}

Page 16: Keep your Wicket application in production

NAVIGATION TEST

@Testpublic void navigateToSecondPage() { WicketTester tester = new WicketTester(); tester.startPage(new FirstPage());}

Page 17: Keep your Wicket application in production

NAVIGATION TEST

@Testpublic void navigateToSecondPage() { WicketTester tester = new WicketTester(); tester.startPage(new FirstPage()); tester.clickLink("link");}

Page 18: Keep your Wicket application in production

NAVIGATION TEST

@Testpublic void navigateToSecondPage() { WicketTester tester = new WicketTester(); tester.startPage(new FirstPage()); tester.clickLink("link"); tester.assertRenderedPage(SecondPage.class);}

Page 19: Keep your Wicket application in production

2. PAGE CHECK

Page 20: Keep your Wicket application in production

PAGES IN EDUARTE

• Pages must have @PageInfo annotation

• Policy file must contain existing pages

• All secure pages must be in the policy file

Page 21: Keep your Wicket application in production

PAGE INFO ANNOTATION@PageInfo( title = "Intake stap 1 van 4", menu = {"Deelnemer > intake"})public class IntakePersonalia extends IntakeWizardPage{ ...}

Page 22: Keep your Wicket application in production

Our build fails for any of these problems...

Page 23: Keep your Wicket application in production

3. ENTITY CHECKER

Page 24: Keep your Wicket application in production

Storing Hibernate entities in your pages is bad...

...mkay

Page 25: Keep your Wicket application in production

WICKET SERIALIZABLE CHECKER

• Runs when page is serialized

• Tries to find non-serializable objects attached to page

• Helpful stacktraces

Page 26: Keep your Wicket application in production

Unable to serialize class: nl.topicus.project.entities.personen.PersoonField hierarchy is: 2 [class=nl.topicus.project.SomePage, path=2] nl.topicus.project.entities.personen.Persoon nl.topicus.project.SomePage.persoon <----- Entity

EXAMPLE STACKTRACE

Page 27: Keep your Wicket application in production

WICKET SERIALIZER CHECK

public class TopicusRequestCycle extends WebRequestCycle { public void onEndRequest() { Page requestPage = getRequest().getPage(); testDetachedObjects(requestPage);

if (getRequestTarget() instanceof IPageRequestTarget) { Page responsePage = getRequestTarget().getPage(); if (responsePage != requestPage) { testDetachedObjects(responsePage); } } }}

Page 28: Keep your Wicket application in production

WICKET SERIALIZER CHECK

if (page == null || page.isErrorPage()) { return;}

try { checker = new EntityAndSerializableChecker( new NotSerializableException()); checker.writeObject(page);} catch (Exception e) { log.error("Couldn't serialize: " + page + ", error : " + ex);}

Page 29: Keep your Wicket application in production

WICKET SERIALIZER CHECK

private void check(Object obj) { Class cls = obj.getClass(); nameStack.add(simpleName); traceStack.add(new TraceSlot(obj, fieldDescription));

if (!(obj instanceof Serializable) && (!Proxy.isProxyClass(cls))) { throw new WicketNotSerializableException(/* ... */); } ... complicated stuff ...}

Page 30: Keep your Wicket application in production

WICKET SERIALIZER CHECK

if (!(obj instanceof Serializable) && (!Proxy.isProxyClass(cls))) { throw new WicketNotSerializableException(/* .. */) .toString(), exception);}if (obj instanceof IdObject) { Serializable id = ((IdObject) obj).getIdAsSerializable(); if (id != null && !(id instanceof Long && ((Long) id) <= 0)) { throw new WicketContainsEntityException(/* ... */); }}

... complicated stuff ...

Page 31: Keep your Wicket application in production

To ensure developers have to fix it immediately...

...an Ajax callback checks for these errors and renders an ErrorPage

Page 32: Keep your Wicket application in production

4. MARKUP VALIDATOR

Page 33: Keep your Wicket application in production

VALID MARKUP...

• Nobody cares about valid markup

• XHTML is dead

Page 34: Keep your Wicket application in production

INVALID MARKUP...

• Browsers do care

• Subtle differences between browser DOM handling

• Ajax becomes a pain

Page 35: Keep your Wicket application in production

WICKET STUFF HTML VALIDATOR

• http://github.com/dashorst/wicket-stuff-markup-validator

• Based on: http://tuckey.org/validation

Page 36: Keep your Wicket application in production

ADD DEPENDENCY TO POM

<dependency> <groupId>org.wicketstuff</groupId> <artifactId>htmlvalidator</artifactId> <version>1.0</version> <scope>test</scope></dependency>

Page 37: Keep your Wicket application in production

ADD FILTER TO WEBAPP

public class MyApplication extends WebApplication { // ...

@Override protected void init() { // only enable the markup filter in DEVELOPMENT mode if(DEVELOPMENT.equals(getConfigurationType())) { getRequestCycleSettings() .addResponseFilter(new HtmlValidationResponseFilter()); } }}

Page 38: Keep your Wicket application in production

DEFINE PROPER DOCTYPE

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head> <title>Foo</title></head><body></body></html>

Page 39: Keep your Wicket application in production

... AND ENDURE THE HORRORS OF VALID MARKUP

Page 40: Keep your Wicket application in production

5. REQUESTLOGGER

Page 41: Keep your Wicket application in production

REQUEST LOGGER

• HTTPD logs are (mostly) useless for Wicket applications

• POST /vocus/app?wicket:interface=:4:lijst::IBehaviorListener...

• GET /vocus/app?wicket:interface=:1084::

• RequestLogger provides decoded information:

• Page, Listener, RequestTarget, SessionID, etc.

Page 42: Keep your Wicket application in production

14:00:19 time=101, event=Interface[ target:DefaultMenuLink(menu:personalia:dropitem page: nl.topicus.gui.student.ToonPersonaliaPage(4) interface: ILinkListener:onLinkClicked], response=PageRequest[ nl.topicus.gui.student.ToonLeerlingRelatiesPage(6)] sessioninfo=[ sessionId=D574D35FF49C047E4F290FE clientInfo=ClientProperties{ remoteAddress=192.0.2.50, browserVersionMajor=7, browserInternetExplorer=true}, organization=Demo School username=administrator], sessionstart=Fri Dec 14 13:59:14 CET 2008, requests=14, totaltime=3314

Page 43: Keep your Wicket application in production

REQUEST LOST PARSER

Page 44: Keep your Wicket application in production

6. RABID MONITORING

Page 45: Keep your Wicket application in production
Page 46: Keep your Wicket application in production

NABAZTAG

• Availability of production applications

• Performance of production applications

• Hudson builds

• Issue tracker

Page 47: Keep your Wicket application in production

THANK YOU!