Confluence has been migrated and upgraded. Please file an INFRA ticket if you see any issues.

Child pages
  • Migration to Wicket 8.0

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.


 

Table of Contents


Important notes before you start

...

Code Block
java
java
    if (RequestCycle.get().find(AjaxRequestTarget.class) == null) {
        // executed for non-ajax-request in Wicket 7
        // never executed in Wicket 8
        ...
    }

See WICKET-6189 84804436 for more details

  • Before Wicket 8 users used to create a custom implementation of IHeaderResponseDecorator to place JavaScript items inside page body:

...

This code doesn't work anymore. See WICKET-6498 84804436 for more details

Environment

...

Replace it with standard Java 8 java.util.function.Supplier<T> which is virtually identical.

Deprecate org.apache.wicket.util.IContextProvider 
Jira
serverASF JIRA
serverId5aa69414-a9e9-3523-82ec-879b028fb15b
keyWICKET-6118

Replace IContextProvider<T, C> with standard Java 8 java.util.function.Function<C, T> which is virtually identical.

As a consequence IPageManagerProvider, IPageRendererProvider and IRequestCycleProvider now override #apply() method instead of #get().

Deprecate org.apache.wicket.protocol.http.documentvalidation.HtmlDocumentValidator 
Jira
serverASF JIRA
serverId5aa69414-a9e9-3523-82ec-879b028fb15b
keyWICKET-6119

Tests based on HtmlDocumentValidator are very fragile. They start to fail as soon as there is a single character change somewhere in the page markup.

We believe that there are very few users of this API. It is recommended to use TagTester and WicketTestCase#executeTest() instead.

Deprecate org.apache.wicket.model.AbstractReadOnlyModel

Use an anonymous instance of IModel instead. Since Wicket 8.0 IModel doesn't require providing implementation of #setObject(Object) method.

Deprecate org.apache.wicket.util.collections.ConcurrentHashSet.java 
Jira
serverASF JIRA
columnskey,summary,type,created,updated,due,assignee,reporter,priority,status,resolution
serverId5aa69414-a9e9-3523-82ec-879b028fb15b
keyWICKET-6783

ConcurrentHashMap.newKeySet() should be used instead

IGenericComponent's setter methods now return the current instance for method chaining

All specialization classes return their type.

AjaxButton, AjaxSubmitLink and AjaxFallbackButton event callback methods no longer get form as second argument 
Jira
serverASF JIRA
serverId5aa69414-a9e9-3523-82ec-879b028fb15b
keyWICKET-6184

 

For consistency with other components and the new lambda support, the submitted form is no longer passed as argument to callback methods (e.g. #onSubmit(), #onClick()) of AjaxButton, AjaxSubmitLink and AjaxFallbackButton. You can call #getForm() instead.

 

RequestCycle#find(Class<T>) returns java.util.Optional 
Jira
serverASF JIRA
serverId5aa69414-a9e9-3523-82ec-879b028fb15b
keyWICKET-6189
Anchor
WICKET-6189
WICKET-6189
WICKET-6189

...

84804436


Code calling RequestCycle#find(Class<T>) has to check whether  a matching IRequestHandler is found. This is now enforced by returning an Optional<T>:

...

All AjaxFallback** components and the containers which use internally AjaxFallback** components, like AjaxTabbedPanel, RatingPanel and TableTree, have been reworked to pass Optional<AjaxRequestTarget> instead of just AjaxRequestTarget to their onXyz() callback methods. This way the application developer should not forget to check that the AjaxRequestTarget is not null. 

AbstractChoice#getChoices() is 'final' now  
Jira
serverASF JIRA
columnskey,summary,type,created,updated,due,assignee,reporter,priority,status,resolution
serverId5aa69414-a9e9-3523-82ec-879b028fb15b
keyWICKET-6132

AbstractChoice#getChoices() has been made final. If the application needs to provide different choices for each render then it should override AbstractChoice#getChoicesModel() instead. The application code would be almost the same as before, it will just need to wrap the final List result in an IModel, most probably ListModel.

ListenerInterfaceRequestHandler simplification
Jira
serverASF JIRA
columnskey,summary,type,created,updated,due,assignee,reporter,priority,status,resolution
serverId5aa69414-a9e9-3523-82ec-879b028fb15b
keyWICKET-6137

RequestListenerInterface was removed:

  • IResourceListener, IBehaviorListener, IOnChangeListener, ILinkListener are replaced by the generic method IRequestListener#onRequest()
  • ListenerInterfaceRequestHandler was renamed to ListenerRequestHandler
  • Component's and Behavior's #canCallListenerInterface() were renamed to #canCallListener()
  • PageSettings#getCallListenerInterfaceAfterExpiry() was renamed to #getCallListenerAfterExpiry.

A Component or Behavior can now implement IRequestListener once only, thus removing the need to include an identifier (e.g. "ILinkListener") in the URL.

If you implemented IResourceListener previously, you have to override IRequestListener#rendersPage() now to return false.

wantOnSelectionChangedNotifications moved to FormComponentUpdatingBehavior 
Jira
serverASF JIRA
columnskey,summary,type,created,updated,due,assignee,reporter,priority,status,resolution
serverId5aa69414-a9e9-3523-82ec-879b028fb15b
keyWICKET-6348

Change notification was moved from CheckBox, DropDownChoice, RadioChoice, CheckGroup/Check and RadioGroup/Radio into a new behavior FormComponentUpdatingBehavior.

Instead of subclasses the component, this behavior can now be added to the component:

Code Block
languagejava
titleFormComponentUpdatingBehavior
// Wicket 7.x
new CheckBox("id", model) {
	protected boolean wantOnSelectionChangedNotifications() {
		return true;
        }

	protected void onSelectionChanged(Boolean newSelection) {
		// do something, page will be rerendered;
	}
};


// Wicket 8.x
new CheckBox("id", model)
.add(new FormComponentUpdatingBehavior() {
	protected void onUpdate() {
		// do something, page will be rerendered;
	}

    protected void onError(RuntimeException ex) {
        super.onError(ex);
    }
});

As with AjaxFormComponentUpdatingBehavior any error during processing of the form component can now be handled in #onError().

Renderers are IDetachable now 
Jira
serverASF JIRA
columnskey,summary,type,created,updated,due,assignee,reporter,priority,status,resolution
serverId5aa69414-a9e9-3523-82ec-879b028fb15b
keyWICKET-6347

Renderers (IChoiceRendere, IOptionRenderer and IAutoCompleteRenderer now take part in detachment as other Wicket concepts like components and models. The owning component is responsible to detach it.

Behavior changesWICKET-649884804436

Application's IHeaderResponseDecorator
Jira
serverASF JIRA
columnskey,summary,type,created,updated,due,assignee,reporter,priority,status,resolution
serverId5aa69414-a9e9-3523-82ec-879b028fb15b
keyWICKET-6498
Anchor
WICKET-6498
WICKET-6498

...

Each Application has an IHeaderResponseDecorator now by default, which decorates header responses with a ResourceAggregator. Projects using their own response decoration (e.g. via JavaScriptFilteredIntoFooterHeaderResponse) have to make sure, that each response is explicitly decorated with a ResourceAggregator too, since Application no longer does it implicitly, e.g.: 


Code Block
languagejava
titleHeader response decoration
setHeaderResponseDecorator(response -> {
            return new ResourceAggregator(new JavaScriptFilteredIntoFooterHeaderResponse(response, "footer"));
});

 


Component#onConfigure() verifies super call
Jira
serverASF JIRA
columnskey,summary,type,created,updated,due,assignee,reporter,priority,status,resolution
serverId5aa69414-a9e9-3523-82ec-879b028fb15b
keyWICKET-6543

...

For convenience IModel class provides a do-nothing implementation of IDetachable#detach() method, so custom implementations are not required to implement it when not needed.

IRequestHandler uses Java 8 default interface method for IRequestHandler#detach()  
Jira
serverASF JIRA
columnskey,summary,type,created,updated,due,assignee,reporter,priority,status,resolution
serverId5aa69414-a9e9-3523-82ec-879b028fb15b
keyWICKET-6146

For convenience IRequestHandler class provides a do-nothing implementation of its #detach() method, so custom implementations are not required to implement it when not needed.

ResourceStreamResource now receives Attributes as a parameter to its #getResourceStream() method 
Jira
serverASF JIRA
serverId5aa69414-a9e9-3523-82ec-879b028fb15b
keyWICKET-6113

For access to the response, the request and its parameters now ResourceStreamResource#getResourceStream() receives an instance of org.apache.wicket.request.resource.IResource.Attributes.

 


Provide serializable versions of java.util.function.(Supplier|Consumer|Function|BiConsumer) 
Jira
serverASF JIRA
serverId5aa69414-a9e9-3523-82ec-879b028fb15b
keyWICKET-5991

java.util.function.Consumer and other classes are not serializable and this makes them unusable in stateful Wicket pages. For this reason Wicket provides org.apache.wicket.model.lambda.WicketSupplier, org.apache.wicket.model.lambda.WicketConsumer, org.apache.wicket.model.lambda.WicketFunction and org.apache.wicket.model.lambda.WicketBiFunction. Those interfaces should be used in method signatures where Java 8 lambdas or method references could be used. At the call site there is nothing specific to be done, i.e. just use lambdas and method references without any casting.

 


Provide IModel implementations which make use of Java 8 lambdas and method references 
Jira
serverASF JIRA
serverId5aa69414-a9e9-3523-82ec-879b028fb15b
keyWICKET-5991

Wicket provides a new implementation of IModel which uses Java 8 consumers and suppliers, i.e. may be used with lambda or method references

  • org.apache.wicket.model.LambdaModel

    Code Block
    languagejava
    titleLambdaModel
    collapsetrue
    Person person = ...;
    IModel<String> personNameModel = new LambdaModel<>(
          () -> person.getName(),
          (name) -> person.setName(name));


  • org.apache.wicket.model.LambdaModel with method references

    Code Block
    languagejava
    titleLambdaModel.of()
    collapsetrue
    Person person = ...;
    IModel<String> personNameModel = LambdaModel.of(person::getName, person::setName);


  • org.apache.wicket.model.LambdaModel can be created with a target model too - note the upper-case 'P' for the function references:

    Code Block
    languagejava
    titleLambdaModel.of(target, ...)
    collapsetrue
    IModel<Person> person = ...;
    IModel<String> personNameModel = LambdaModel.of(person, Person::getName, Person::getName);


IGenericComponent is a mixin/trait interface 
Jira
serverASF JIRA
serverId5aa69414-a9e9-3523-82ec-879b028fb15b
keyWICKET-6117

IGenericComponent uses Java 8 default methods to implement #setModel(IModel<T>), #getModel(), #setModelObject(T) and #getModelObject() by delegating to the respective get/setDefaultModel[Object] methods.

This way it could be easily used by any Component by just implementing it.

IModel is a @FunctionalInterface now

IModel provides default implementations of #detach() (do nothing) and #setObject(T) (throws UnsupportedOperationException), so it is possible to use it as a functional interface.

Code Block
languagejava
titleIModel as functional interface
collapsetrue
new Link<String>("", () -> "abc") {
   @Override
   public void onClick()
   {
     // ...
   }
};
 
Label label = new Label("id", person::getName); // the method reference is actually IModel<String>

Provide LambdaColumn - IColumn implementation that uses java.util.function.Function 
Jira
serverASF JIRA
serverId5aa69414-a9e9-3523-82ec-879b028fb15b
keyWICKET-6121

Code Block
languagejava
titleLambdaColumn
collapsetrue
 columns.add(new LambdaColumn<Contact, String>(new Model<>("Last Name"), "lastName", Contact::getLastName)

IColumn uses Java 8 default interface method for IColumn#isSortable()  Git commit

For convenience IColumn class provides an implementation of #isSortable() method that uses #getSortProperty() to decide. Just like AbstractColumn did until Wicket 7.

IColumn provides methods for column's header rowspan/colspan 
Jira
serverASF JIRA
serverId5aa69414-a9e9-3523-82ec-879b028fb15b
keyWICKET-6095

New methods have been added to help manipulating the tables' headers: IColumn#getHeaderColspan() and IColumn#getHeaderRowSpan(). Both of them return 1, so the header cells do not span by default.

 


IRequestCycleListener notified of all IRequestHandlers 
Jira
serverASF JIRA
columnskey,summary,type,created,updated,due,assignee,reporter,priority,status,resolution
serverId5aa69414-a9e9-3523-82ec-879b028fb15b
keyWICKET-6129

IRequestCycleListeners are now notified of the execution of all IRequestHandlers, including those scheduled by other handlers, those replacing other handlers, and any handler executed due to an exception:

  • #onRequestHandlerResolved(RequestCycle, IRequestHandler) - any handler to be executed
  • #onRequestHandlerExecuted(RequestCycle, IRequestHandler) - any handler successfully executed without an exception

RequestHandlerStack is now renamed to RequestHandlerExecutor.

...

  • Spring Framework 4.3.x
  • Jetty 9.4.x (used in the Quickstart application archetype and for internal Wicket testing)
  • Mockito 2.x (for internal testing)
  • Depend on com.github.openjson:openjson instead of using local copies of org.json/com.tdunning:open-json

...