Versions Compared

Key

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

...

The

...

trouble

...

with

...

Generics

...

Excerpt

...

hidden

...

true

...

Hidden

...

Excerpt

...

Panel
borderStylesolid
titleTable of contents
Table of Contents
minLevel2
Info

You are kindly requested to modify/tweak and work on this document. Just one thing: KEEP IT CIVIL!

This document tries to capture the benefits and doubts we have regarding generics in Wicket 1.4. Ultimately we need to find a way where the Framework and Wicket Community can move onward to Wicket 1.5/2.0

...

with

...

Java

...

5

...

as

...

a

...

basis.

...

Generics

...

Rock!

...

Java

...

generics

...

are

...

good

...

for

...

type

...

safety

...

throughout

...

your

...

code.

...

They

...

document

...

the

...

code

...

directly

...

with

...

intent:

...

List<Person>

...

leaves

...

little

...

to

...

the

...

imagination

...

as

...

to

...

what

...

goes

...

into

...

the

...

list.

...

These

...

benefits

...

are

...

a

...

great

...

asset

...

to

...

Wicket.

...

Wicket

...

uses

...

the

...

concept

...

of

...

models

...

to

...

provide

...

components

...

with

...

the

...

data

...

that

...

needs

...

to

...

be

...

rendered.

...

Until

...

recently

...

Wicket

...

was

...

Java

...

1.4

...

based,

...

and

...

a

...

lot

...

of

...

components

...

suffered

...

from

...

the

...

lack

...

of

...

generified

...

models.

...

Take

...

for

...

instance

...

the

...

ListView:

Generics Suck!

TBD

Generics are warranted for IModel but too much verbosity for Component

If there is any place in Wicket which clearly holds typed data, it is the models (the IModel interface). In practice, one ends up creating a lot of custom components without models, such as different subclasses of MarkupContainer and possibly Page, and here the Component generification just adds more verbosity to the code.

Typically when starting to use a custom component, you start by typing its constructor call, so the constructor of a custom component is a crucial place for making clean and easy APIs. The possibility of giving type arguments to the IModel instance being passed in there is great, DropDownChoice is a prime example as it also has constructors with a List that needs to contain objects of the same type as the model. However,

Code Block
java
java
}}:

h2. Generics Suck!

TBD

h2. Generics are warranted for {{IModel}} but too much verbosity for {{Component}}

If there is any place in Wicket which clearly holds typed data, it is the models (the {{IModel}} interface). In practice, one ends up creating a lot of custom components without models, such as different subclasses of {{MarkupContainer}} and possibly {{Page}}, and here the {{Component}} generification just adds more verbosity to the code. 

Typically when starting to use a custom component, you start by typing its constructor call, so the constructor of a custom component is a crucial place for making clean and easy APIs. The possibility of giving type arguments to the {{IModel}} instance being passed in there is great, [DropDownChoice|http://svn.apache.org/repos/asf/wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/html/form/DropDownChoice.java] is a prime example as it also has constructors with a List that needs to contain objects of the same type as the model. However, 
{code:java}
DropDownChoice fruit = new DropDownChoice("fruit", new Model<Fruit>(), Arrays.asList(apple, orange, banana));
{code}

is

...

better

...

than

Code Block
java
java

{code:java}
DropDownChoice<Fruit> fruit = new DropDownChoice<Fruit>("fruit", new Model<Fruit>(), Arrays.asList(apple, orange, banana));
{code}

Also

...

when

...

using

...

2.0

...

the

...

experience

...

was

...

that

...

IModel

...

type

...

was

...

excellent,

...

but

...

Component

...

type

...

was

...

more

...

like

...

noise.

...

When

...

using

...

1.3,

...

the

...

lack

...

of

...

types

...

has

...

hardly

...

caused

...

trouble;

...

mostly

...

types

...

would

...

be

...

helpful

...

when

...

first

...

creating

...

a

...

new

...

component.

...

Once

...

you

...

have

...

the

...

component

...

constructed

...

and

...

are

...

calling

...

getModelObject()

...

on

...

it,

...

you're

...

typically

...

sure

...

of

...

what

...

to

...

expect.

...

There

...

have

...

not

...

been

...

difficult

...

problems

...

concerning

...

objects

...

of

...

wrong

...

type

...

inside

...

models.

...

In

...

this

...

approach,

...

using

...

getModelObject()

...

you

...

cast

...

the

...

same

...

as

...

in

...

1.3,

...

and

...

for

...

getModel()

...

you

...

can

...

do

...

the

...

necessary

...

casting

...

cleanly

...

,

...

which

...

leaves

...

you

...

in

...

a

...

situation

...

better

...

than

...

in

...

1.3.

...


(Timo

...

Rantalaiho)

...

I

...

mostly

...

agree

...

with

...

Timo.

...

The

...

only

...

thing

...

we

...

lose

...

from

...

Component

...

is

...

generification

...

of

...

IConverter.

...

Since

...

IConverter

...

is

...

mostly

...

only

...

important

...

in

...

FormComponent

...

perhaps

...

we

...

can

...

fully

...

type

...

FormComponent

...

which

...

would

...

allow

...

us

...

to

...

have

...

typesafe

...

converters

...

AND

...

validators.

...


(Igor

...

Vaynberg)

...

If

...

we

...

dont

...

do

...

Component

...

but

...

we

...

do

...

specific

...

subtypes

...

like

...

FormComponent

...

that

...

the

...

above

...

DropDownChoice

...

example

...

still

...

has

...

that

...

signature..

...


and

...

then

...

i

...

also

...

vote

...

for

...

Repeaters

...

to

...

be

...

generified,

...

because

...

especially

...

in

...

the

...

onPopulate

...

it

...

is

...

very

...

descriptive

...

what

...

you

...

get..

...


But

...

i

...

think

...

people

...

will

...

then

...

start

...

complaining

...

because

...

they

...

are

...

using

...

Links

...

a

...

lot

...

and

...

there

...

model

...

object..

...

So

...

then

...

we

...

do

...

get

...

the

...

question

...

constantly

...

on

...

the

...

list

...

Why

...

is

...

this

...

and

...

Why

...

isnt

...

that...

...

(i

...

think)

...


I

...

still

...

dont

...

find

...

this

...

that

...

bad..

...

It

...

really

...

describes

...

it:

Code Block
java
java

{code:java}
DropDownChoice<Fruit> fruit = new DropDownChoice<Fruit>("fruit", new Model<Fruit>(), Arrays.asList(apple, orange, banana));
{code:java

because what you also could do is this:

Code Block
java
java
}

because what you also could do is this:

{code:java}
DropDownChoice<Fruit> fruit = new DropDownChoice<Fruit>("fruit", Arrays.asList(apple, orange, banana));
{code:java}

and yes i 

and yes i know..

...

this

...

is

...

somewhere

...

not

...

really

...

type

...

safe..because

...

now

...

a

...

CompoundModel

...

is

...

used

...

and

...

that

...

is

...

based

...

on

...

strings..

...


But

...

in

...

the

...

code

...

is

...

more

...

descriptive..

...

but

...

i

...

guess

...

somehow

...

we

...

should

...

have

...

a warning (sad)
And this is also the reason why i am also working on type safe property models.
(Johan Compagner)

Suggestion 1 - setResponsePage() signature

The initial issue that started this discussion was a problem with this method signature:

Code Block
 warning :(
And this is also the reason why i am also working on type safe property models.
(Johan Compagner)

h2.  -Suggestion 1 - {{setResponsePage()}} signature-

The initial issue that started this discussion was a problem with this method signature:

{code}
public final void setResponsePage(final Class<? extends Page<?>> cls, PageParameters parameters)
{
    getRequestCycle().setResponsePage(cls, parameters);
}
{code}

We

...

could

...

change

...

this

...

to:

{
Code Block
}
@SuppressWarnings({"unchecked"})
public final void setResponsePage(final Class<?> cls, PageParameters parameters)
{
    final Class<? extends Page<?>> castCls = (Class<? extends Page<?>>) cls;
    getRequestCycle().setResponsePage(castCls, parameters);
}
{code}

This

...

way

...

(a)

...

users

...

migrating

...

to

...

1.4

...

don't

...

get

...

tons

...

of

...

warnings/errors

...

and

...

(b)

...

if

...

they

...

pass

...

in

...

the

...

wrong

...

thing,

...

a

...

class

...

cast

...

exception

...

will

...

be

...

thrown

...

quickly.

...

NOTE:

...

This

...

is

...

just

...

an

...

example

...

-

...

we

...

may

...

wish

...

to

...

move

...

the

...

cast

...

into

...

the

...

getRequestCycle()

...

call

...

...

...

My

...

idea

...

is

...

to

...

dial

...

back

...

the

...

generics

...

on

...

some

...

of

...

the

...

API

...

calls

...

like

...

this

...

one

...

and

...

others

...

that

...

cause

...

pain,

...

but

...

leave

...

the

...

generics

...

for

...

useful

...

things

...

like

...

getModelObject().

...

-Doug Donohoe

...

This is already resolved with the following signature:

Code Block
 Donohoe

-----
This is already resolved with the following signature:
{code}
public final <C extends Page<?>> void setResponsePage(final Class<C> cls, PageParameters parameters)
{
    getRequestCycle().setResponsePage(cls, parameters);
}
{code}

Gerolf Seitz

Suggestion 2 - RestartResponseAtInterceptPageException constructor

I agree with Doug, and with suggestion 1 above on setResponsePage changing to take Class<?>

I think another example is the constructor of RestartResponseAtInterceptPageException (and similar classes) that take a class as an argument.

Code Block
 Seitz

h2.  -Suggestion 2 - RestartResponseAtInterceptPageException constructor-

I agree with Doug, and with suggestion 1 above on setResponsePage changing to take Class<?>

I think another example is the constructor of RestartResponseAtInterceptPageException (and similar classes) that take a class as an argument.

{code}
	public RestartResponseAtInterceptPageException(final Class< ? extends Page< ? >> interceptPageClass)
	{
		if (interceptPageClass == null)
		{
			throw new IllegalStateException("Argument pageClass cannot be null");
		}
		redirectToInterceptPage(interceptPageClass);
	}
{code}

We

...

could

...

change

...

this

...

to:

{
Code Block
}
public RestartResponseAtInterceptPageException(final Class<?> interceptPageClass)
{
	if (interceptPageClass == null || !Page.class.isAssignableFrom(interceptPageClass))
	{
		throw new IllegalStateException("Argument pageClass cannot be null and must inherit from Page.class");
	}
	redirectToInterceptPage(interceptPageClass);
}
{code}

This,

...

for

...

the

...

same

...

reason

...

as

...

suggestion

...

1

...

-

...

it's

...

not

...

very

...

likely

...

that

...

someone

...

is

...

going

...

to

...

pass

...

a

...

non-page-child

...

class

...

into

...

these

...

methods

...

or

...

constructors,

...

so

...

the

...

benefit

...

is

...

minimal,

...

but

...

the

...

strictly

...

generified

...

versions

...

penalize

...

you

...

if

...

your

...

page

...

class

...

is

...

not

...

also

...

generified,

...

which

...

would

...

be

...

confusing

...

to

...

new

...

users.

...

...

Same as above.

...

-Gerolf

...

Seitz