Wicket 6

39
Wicket 6

description

Presentation on Wicket 6 I gave at BedCon 2013.

Transcript of Wicket 6

Page 1: Wicket 6

Wicket 6

Page 2: Wicket 6

?

Page 3: Wicket 6

Quickstart

Page 4: Wicket 6
Page 5: Wicket 6

Auf geht‘s

Page 6: Wicket 6

Unmanaged aber nicht einsam

Managed

WeblayerGlue

ORMManagement

Security...

Wicket

Weblayer

API

Page 7: Wicket 6

Servlet 2.5 Container<application>.war

WicketFilterWebApplication

Aufbau

Page 8: Wicket 6

public class WicketApplication extends AuthenticatedWebApplication { @Override public HomePage getHomePage() { return HomePage.class; } @Override public void init() { super.init(); getSecuritySettings().setAuthorizationStrategy( new AnnotationsRoleAuthorizationStrategy(this)); getMarkupSettings().setAutomaticLinking(true); mountPage("/dummy", PlainLayoutPage.class); } @Override protected Class<? extends AbstractAuthenticatedWebSession> getWebSessionClass() { return UserAuthenticatedWebSession.class; } @Override protected Class<? extends WebPage> getSignInPageClass() { return SignInWithoutRememberMePage.class; }}

Page 9: Wicket 6

enabling component-oriented, programmatic manipulation of markup*

*http://wicket.apache.org/meet/vision.html

Page 10: Wicket 6

Goodold

Java+ HTML

Page 11: Wicket 6

Component.java

Component

Component.html

Component.properties

Page 12: Wicket 6

UserUpdatePanel.java

UserUpdatePanel.properties

UserUpdatePanel.html

public class UserUpdatePanel extends Panel{ public static final String PASSWORD = "password"; public static final String PASSWORD_REPEAT = "passwordRepeat"; public static final String USER_UPDATE_FORM = "userUpdateForm"; @Autowired private UserRepository userRepository; public UserUpdatePanel(String id, IModel<User> model) { super(id, model); FormComponent<String> password = new PasswordTextField(PASSWORD); FormComponent<String> passwordRepeat = new PasswordTextField(PASSWORD_REPEAT, Model.of("")); Form<User> userUpdateForm = new Form<User>(USER_UPDATE_FORM, new CompoundPropertyModel<User>(model)) { @Override protected void onSubmit() { userRepository.save(getModelObject()); } }; add(userUpdateForm .add(new TextField<String>("name")) .add(password) .add(passwordRepeat) .add(new AjaxFallbackButton("submit", userUpdateForm) {}) .add(new EqualInputValidator(password, passwordRepeat)) ); }}

<!DOCTYPE html> <html xmlns:wicket="http://wicket.apache.org"> <head> <meta charset="utf-8"> <title>Wicket Example App</title> </head> <body> <wicket:panel> <form wicket:id="userUpdateForm"> <fieldset> <legend><wicket:message key="userUpdateTitle"/></legend> <label wicket:for="name"><wicket:message key="username"/></label> <input type="text" wicket:id="name"/> <label wicket:for="password"><wicket:message key="password"/></label> <input type="password" wicket:id="password"/> <label wicket:for="passwordRepeat"><wicket:message key="passwordRepeat"/></label> <input type="password" wicket:id="passwordRepeat"/> <p><input type="submit" value="submit" wicket:id="submit"/></p> </fieldset> </form> </wicket:panel> </body> </html>

userUpdateTitle=Benutzer anpassenusername=Benutzernamepassword=PasswortpasswordRepeat=Passwort wiederholen

Page 13: Wicket 6

public class UserUpdatePanel extends Panel{ public static final String PASSWORD = "password"; public static final String PASSWORD_REPEAT = "passwordRepeat"; public static final String USER_UPDATE_FORM = "userUpdateForm"; @Autowired private UserRepository userRepository; public UserUpdatePanel(String id, IModel<User> model) { super(id, model); FormComponent<String> password = new PasswordTextField(PASSWORD); FormComponent<String> passwordRepeat = new PasswordTextField(PASSWORD_REPEAT, Model.of("")); Form<User> userUpdateForm = new Form<User>(USER_UPDATE_FORM, new CompoundPropertyModel<User>(model)) { @Override protected void onSubmit() { userRepository.save(getModelObject()); } }; add(userUpdateForm .add(new TextField<String>("name")) .add(password) .add(passwordRepeat) .add(new AjaxFallbackButton("submit", userUpdateForm) {}) .add(new EqualInputValidator(password, passwordRepeat)) ); }}

Page 14: Wicket 6

<!DOCTYPE html> <html xmlns:wicket="http://wicket.apache.org"> <head> <meta charset="utf-8"> <title>Wicket Example App</title> </head> <body> <wicket:panel> <form wicket:id="userUpdateForm"> <fieldset> <legend><wicket:message key="userUpdateTitle"/></legend> <input type="text" wicket:id="name"/> <input type="password" wicket:id="password"/> <input type="password" wicket:id="passwordRepeat"/> <p><input type="submit" value="submit" wicket:id="submit"/></p> </fieldset> </form> </wicket:panel> </body> </html>

Page 15: Wicket 6

wicket:extend

wicket:child

wicket:id

wicket:message

wicket:remove

wicket:headwicket:container

wicket:border

wicket:body

wicket:fragment

wicket:panelwicket:link

<html xmlns:wicket="http://wicket.apache.org">

Page 16: Wicket 6

KeineLogik

Templateim

Page 17: Wicket 6

Inheritance

UserUpdatePanel

MyUserUpdatePanel

Page 18: Wicket 6

public class MyUserUpdatePanel extends UserUpdatePanel{ public UserUpdatePanel(String id, IModel<User> model) { super(id, model); }}

<!DOCTYPE html> <html xmlns:wicket="http://wicket.apache.org"> <head> <meta charset="utf-8"> <title>Wicket Example App</title> </head> <body> <wicket:panel> <form wicket:id="userUpdateForm"> <fieldset> <legend><wicket:message key="userUpdateTitle"/></legend> <input type="text" wicket:id="name"/> <input type="password" wicket:id="password"/> <input type="password" wicket:id="passwordRepeat"/> <p><input type="submit" value="submit" wicket:id="submit"/></p> </fieldset> </form> </wicket:panel> </body> </html>

MyUserUpdatePanel.html

MyUserUpdatePanel.propertiesuserUpdateTitle=Lustiges Felderraten

Page 19: Wicket 6
Page 20: Wicket 6

MyUserUpdatePanel UserUpdatePanel Object

Got my stuff?

MyUserUpdatePanel UserUpdatePanel Object Application

Markup

Properties

...

...

Page 21: Wicket 6

Datenbeschaffung

package de.bootcamp.wicket.web.page; public interface IModel<T> extends IDetachable{ T getObject(); void setObject(final T object);}

public UserUpdatePanel(String id, IModel<User> model)

Page 22: Wicket 6

public class UserUpdatePanel extends Panel{ !... public UserUpdatePanel(String id, IModel<User> model) { super(id, model); FormComponent<String> password = new PasswordTextField(PASSWORD, new PropertyModel<String>(model, "password") ); FormComponent<String> passwordRepeat = new PasswordTextField(PASSWORD_REPEAT, Model.of("")); Form<User> userUpdateForm = new Form<User>(USER_UPDATE_FORM, new CompoundPropertyModel<User>(model)) { @Override protected void onSubmit() { userRepository.save(getModelObject()); } }; ... }}

Page 23: Wicket 6

• Entkopplung Beschaffung / Verwendung!

• Lazy!

• Chainable!

• Leicht testbar

IModel

Page 24: Wicket 6

Behavior

• AttributeAppender/AttributeModifier!

• AjaxSelfUpdatingBehavior!

• AjaxEventBehavior!

• ...

Component! Behavior.add( )

Page 25: Wicket 6

Alles zusammen

Page 26: Wicket 6

Pagepublic class HomePage extends WebPage { private static final long serialVersionUID = 1L; @SpringBean private BusinessService businessService; public HomePage(final PageParameters parameters) { super(parameters); IModel<User> userModel = new LoadableDetachableModel<User>() { @Override protected User load() { return businessService.findUserByName("user1"); } }; add(new Label("name", new PropertyModel<String>(userModel,"name"))); add(new MyUserUpdatePanel("userUpdatePanel", userModel)); ! add(new AjaxLink("adminLink") { @Override public void onClick(AjaxRequestTarget target) { setResponsePage(AdminPage.class); } }); }}

Page 27: Wicket 6

Praxis!!!

Page 28: Wicket 6

AJAX

• Seit Wicket 6: JQuery!!

• Transparente Verwendung!

• Maßgeblicher Bestandteil des Wicket-Kerns!

• Einfach über Behaviors erweiterbar!

• Weiterführung der Komponentisierung

Page 29: Wicket 6
Page 30: Wicket 6

NoScript>

AjaxFallbackButton!AjaxFallbackDefaultDataTable!AjaxFallbackHeadersToolbar!

AjaxFallbackLink!...

AJAX

Page 31: Wicket 6

Kopplung

Callbacks

Events

Page 32: Wicket 6

Component

public interface IEventSource{ <T> void send(IEventSink sink, Broadcast broadcast, T payload);}

public interface IEventSink{ void onEvent(IEvent<?> event);}

• Schwache Kopplung!

• hohe Flexibilität!

• weniger Boilerplate

Page 33: Wicket 6

Ajax Default Event

Page 34: Wicket 6

... @Override public void onEvent(IEvent<?> event) { if(event.getPayload() instanceof AjaxRequestTarget) { ((AjaxRequestTarget)event.getPayload()).add(this); } }...

Page 35: Wicket 6

WicketTester private WicketTester wicketTester; @Before public void setUp() { wicketTester = new WicketTester(); } @After public void tearDown() { wicketTester.destroy(); } @Test public void testCreateTask() throws Exception{ IModel<TaskList> taskListMock = mock(IModel.class); User testUser = new User(); CreateTaskPanel createTaskPanel = new CreateTaskPanel("testPanel", testUser, taskListMock); wicketTester.startComponentInPage(createTaskPanel); wicketTester.assertComponent("testPanel", CreateTaskPanel.class); FormTester formTester = wicketTester.newFormTester("testPanel:taskForm"); formTester.setValue("title", "taskTitle"); formTester.submit(); ArgumentCaptor<Task> taskCaptor = ArgumentCaptor.forClass(Task.class); verify(taskServiceMock).create(taskCaptor.capture()); assertEquals("taskTitle", taskCaptor.getValue().getTitle()); assertEquals(testUser, taskCaptor.getValue().getUser()); }

Page 36: Wicket 6

Ressourcen

• JavaScript!

• CSS!

• Bilder!

• PDF!

• ...

Page 37: Wicket 6

public class DataTablesResource extends JavaScriptResourceReference { private static final Set<HeaderItem> deps; static { HashSet<HeaderItem> items = new HashSet<HeaderItem>(); items.add(JavaScriptHeaderItem.forReference(JQueryResourceReference.get())); deps = Collections.unmodifiableSet(items); } private static final DataTablesResource instance = new DataTablesResource(); private DataTablesResource() { super(DataTablesResource.class, "jquery.dataTables.js"); } public static DataTablesResource get() { return instance; } @Override public Iterable<? extends HeaderItem> getDependencies() { return deps; }}

... !@Overridepublic void renderHead(IHeaderResponse response) { super.renderHead(response); response.render(JavaScriptHeaderItem.forReference(DataTablesResource.get()));} !...

Page 38: Wicket 6

Und weiter?

• Optimierung der verwendeten Ressourcen!

• Kontrolle der URL!

• Dependency Management!

• JavaScript ResourceBundles!

• Übersteuern von Versionen

Page 39: Wicket 6

http://code.google.com/p/wicket-guide/

Wicket-Guide

GET IT!