Get your application
     in production...




               ...and keep your
               weekends free
              ...
6 WAYS TO KEEP YOUR JOB
OUT OF YOUR WEEKEND
1. USE WICKET TESTER
WICKETTESTER

• Test   components directly, or their markup

• Runs   tests without starting server

• Ajax   testing (ser...
HELLOWORLD TEST
@Test
public void labelContainsHelloWorld() {
}
HELLOWORLD TEST
@Test
public void labelContainsHelloWorld() {
  WicketTester tester = new WicketTester();
}
HELLOWORLD TEST
@Test
public void labelContainsHelloWorld() {
  WicketTester tester = new WicketTester();
  tester.startPa...
HELLOWORLD TEST
@Test
public void labelContainsHelloWorld() {
  WicketTester tester = new WicketTester();
  tester.startPa...
LINK TEST
@Test
public void countingLinkClickTest() {
}
LINK TEST
@Test
public void countingLinkClickTest() {
  WicketTester tester = new WicketTester();
}
LINK TEST
@Test
public void countingLinkClickTest() {
  WicketTester tester = new WicketTester();
  tester.startPage(LinkC...
LINK TEST
@Test
public void countingLinkClickTest() {
  WicketTester tester = new WicketTester();
  tester.startPage(LinkC...
LINK TEST
@Test
public void countingLinkClickTest() {
  WicketTester tester = new WicketTester();
  tester.startPage(LinkC...
LINK TEST
@Test
public void countingLinkClickTest() {
  WicketTester tester = new WicketTester();
  tester.startPage(LinkC...
NAVIGATION TEST
@Test
public void navigateToSecondPage() {
}
NAVIGATION TEST
@Test
public void navigateToSecondPage() {
  WicketTester tester = new WicketTester();
  tester.startPage(...
NAVIGATION TEST
@Test
public void navigateToSecondPage() {
  WicketTester tester = new WicketTester();
  tester.startPage(...
NAVIGATION TEST
@Test
public void navigateToSecondPage() {
  WicketTester tester = new WicketTester();
  tester.startPage(...
2. PAGE CHECK
PAGES IN EDUARTE


• Pages    must have @PageInfo annotation

• Policy   file must contain existing pages

• All   secure p...
PAGE INFO ANNOTATION
@PageInfo(
  title = quot;Intake stap 1 van 4quot;,
  menu = {quot;Deelnemer > intakequot;}
)
public ...
Our build fails for any
 of these problems...
3. ENTITY CHECKER
Storing Hibernate entities in
your pages is bad...



                   ...mkay
WICKET SERIALIZABLE
                 CHECKER


• Runs    when page is serialized

• Tries   to find non-serializable object...
EXAMPLE STACKTRACE

Unable to serialize class: nl.topicus.project.entities.personen.Persoon
Field hierarchy is:
  2 [class...
WICKET SERIALIZER CHECK
public class TopicusRequestCycle extends WebRequestCycle {
  public void onEndRequest() {
      Pa...
WICKET SERIALIZER CHECK
if (page == null || page.isErrorPage()) {
    return;
}

try {
   checker = new EntityAndSerializa...
WICKET SERIALIZER CHECK
private void check(Object obj) {
   Class cls = obj.getClass();
   nameStack.add(simpleName);
   t...
WICKET SERIALIZER CHECK
if (!(obj instanceof Serializable) && (!Proxy.isProxyClass(cls))) {
    throw new WicketNotSeriali...
To ensure developers
have to fix it immediately...


     ...an Ajax callback checks for these
        errors and renders a...
4. MARKUP VALIDATOR
VALID MARKUP...



• Nobody   cares about valid markup

• XHTML    is dead
INVALID MARKUP...


             do care
• Browsers

• Subtle   differences between browser DOM handling

• Ajax   becomes...
WICKET STUFF HTML
              VALIDATOR


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

• Based   on: http...
ADD DEPENDENCY TO POM
<dependency>
  <groupId>org.wicketstuff</groupId>
  <artifactId>htmlvalidator</artifactId>
  <versio...
ADD FILTER TO WEBAPP
public class MyApplication extends WebApplication {
  // ...

    @Override
    protected void init()...
DEFINE PROPER DOCTYPE
<!DOCTYPE html PUBLIC quot;-//W3C//DTD XHTML 1.0 Transitional//EN
  quot;http://www.w3.org/TR/xhtml1...
... AND ENDURE THE HORRORS
OF VALID MARKUP
5. REQUESTLOGGER
REQUEST LOGGER

• HTTPD   logs are (mostly) useless for Wicket applications

 • POST   /vocus/app?wicket:interface=:4:lijs...
14:00:19 time=101,
   event=Interface[
      target:DefaultMenuLink(menu:personalia:dropitem
      page: nl.topicus.gui.st...
REQUEST LOST PARSER
6. RABID MONITORING
NABAZTAG


• Availability   of production applications

• Performance       of production applications

• Hudson     build...
THANK YOU!
Keep your Wicket application in production
Upcoming SlideShare
Loading in …5
×

Keep your Wicket application in production

6,440 views

Published on

Published in: Business, Technology
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
6,440
On SlideShare
0
From Embeds
0
Number of Embeds
54
Actions
Shares
0
Downloads
138
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

Keep your Wicket application in production

  1. 1. Get your application in production... ...and keep your weekends free Martijn Dashorst Topicus
  2. 2. 6 WAYS TO KEEP YOUR JOB OUT OF YOUR WEEKEND
  3. 3. 1. USE WICKET TESTER
  4. 4. 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
  5. 5. HELLOWORLD TEST @Test public void labelContainsHelloWorld() { }
  6. 6. HELLOWORLD TEST @Test public void labelContainsHelloWorld() { WicketTester tester = new WicketTester(); }
  7. 7. HELLOWORLD TEST @Test public void labelContainsHelloWorld() { WicketTester tester = new WicketTester(); tester.startPage(HelloWorld.class); }
  8. 8. HELLOWORLD TEST @Test public void labelContainsHelloWorld() { WicketTester tester = new WicketTester(); tester.startPage(HelloWorld.class); tester.assertLabel(quot;messagequot;, quot;Hello, World!quot;); }
  9. 9. LINK TEST @Test public void countingLinkClickTest() { }
  10. 10. LINK TEST @Test public void countingLinkClickTest() { WicketTester tester = new WicketTester(); }
  11. 11. LINK TEST @Test public void countingLinkClickTest() { WicketTester tester = new WicketTester(); tester.startPage(LinkCounter.class); }
  12. 12. LINK TEST @Test public void countingLinkClickTest() { WicketTester tester = new WicketTester(); tester.startPage(LinkCounter.class); tester.assertModelValue(quot;labelquot;, 0); }
  13. 13. LINK TEST @Test public void countingLinkClickTest() { WicketTester tester = new WicketTester(); tester.startPage(LinkCounter.class); tester.assertModelValue(quot;labelquot;, 0); tester.clickLink(quot;linkquot;); }
  14. 14. LINK TEST @Test public void countingLinkClickTest() { WicketTester tester = new WicketTester(); tester.startPage(LinkCounter.class); tester.assertModelValue(quot;labelquot;, 0); tester.clickLink(quot;linkquot;); tester.assertModelValue(quot;labelquot;, 1); }
  15. 15. NAVIGATION TEST @Test public void navigateToSecondPage() { }
  16. 16. NAVIGATION TEST @Test public void navigateToSecondPage() { WicketTester tester = new WicketTester(); tester.startPage(new FirstPage()); }
  17. 17. NAVIGATION TEST @Test public void navigateToSecondPage() { WicketTester tester = new WicketTester(); tester.startPage(new FirstPage()); tester.clickLink(quot;linkquot;); }
  18. 18. NAVIGATION TEST @Test public void navigateToSecondPage() { WicketTester tester = new WicketTester(); tester.startPage(new FirstPage()); tester.clickLink(quot;linkquot;); tester.assertRenderedPage(SecondPage.class); }
  19. 19. 2. PAGE CHECK
  20. 20. PAGES IN EDUARTE • Pages must have @PageInfo annotation • Policy file must contain existing pages • All secure pages must be in the policy file
  21. 21. PAGE INFO ANNOTATION @PageInfo( title = quot;Intake stap 1 van 4quot;, menu = {quot;Deelnemer > intakequot;} ) public class IntakePersonalia extends IntakeWizardPage { ... }
  22. 22. Our build fails for any of these problems...
  23. 23. 3. ENTITY CHECKER
  24. 24. Storing Hibernate entities in your pages is bad... ...mkay
  25. 25. WICKET SERIALIZABLE CHECKER • Runs when page is serialized • Tries to find non-serializable objects attached to page • Helpful stacktraces
  26. 26. EXAMPLE STACKTRACE Unable to serialize class: nl.topicus.project.entities.personen.Persoon Field hierarchy is: 2 [class=nl.topicus.project.SomePage, path=2] nl.topicus.project.entities.personen.Persoon nl.topicus.project.SomePage.persoon <----- Entity
  27. 27. 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); } } } }
  28. 28. WICKET SERIALIZER CHECK if (page == null || page.isErrorPage()) { return; } try { checker = new EntityAndSerializableChecker( new NotSerializableException()); checker.writeObject(page); } catch (Exception e) { log.error(quot;Couldn't serialize: quot; + page + quot;, error: quot; + ex); }
  29. 29. 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 ... }
  30. 30. 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 ...
  31. 31. To ensure developers have to fix it immediately... ...an Ajax callback checks for these errors and renders an ErrorPage
  32. 32. 4. MARKUP VALIDATOR
  33. 33. VALID MARKUP... • Nobody cares about valid markup • XHTML is dead
  34. 34. INVALID MARKUP... do care • Browsers • Subtle differences between browser DOM handling • Ajax becomes a pain
  35. 35. WICKET STUFF HTML VALIDATOR • http://github.com/dashorst/wicket-stuff-markup-validator • Based on: http://tuckey.org/validation
  36. 36. ADD DEPENDENCY TO POM <dependency> <groupId>org.wicketstuff</groupId> <artifactId>htmlvalidator</artifactId> <version>1.0</version> <scope>test</scope> </dependency>
  37. 37. 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()); } } }
  38. 38. DEFINE PROPER DOCTYPE <!DOCTYPE html PUBLIC quot;-//W3C//DTD XHTML 1.0 Transitional//EN quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtdquot;> <html xmlns=quot;http://www.w3.org/1999/xhtmlquot;> <head> <title>Foo</title> </head> <body> </body> </html>
  39. 39. ... AND ENDURE THE HORRORS OF VALID MARKUP
  40. 40. 5. REQUESTLOGGER
  41. 41. 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.
  42. 42. 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
  43. 43. REQUEST LOST PARSER
  44. 44. 6. RABID MONITORING
  45. 45. NABAZTAG • Availability of production applications • Performance of production applications • Hudson builds • Issue tracker
  46. 46. THANK YOU!

×