I'm upgrading a Vaadin 23.2 app to Vaadin 24.8. I have a compilation error on one of my components. It's a simple custom field with this signature:
public class MyField extends CustomField<String> {
IntelliJ IDEA doesn't show any error, but Gradle compilation (JDK17) throws:
error: HasValue cannot be inherited with different arguments: <?,java.lang.String> and <com.vaadin.flow.component.AbstractField.ComponentValueChangeEvent<?,java.lang.String>,java.lang.String>
without any indication of class name or line number, but when I remove the class the issue is gone.
I see that CustomField
now effectively inherits from HasValue
twice: by extending AbstractField
and by implementing InputField
, but I fail to see why these clash, and what I can do about that.
I'm on JDK17 (Eclipse Termurin), I've tried the latest Corretto 17 release but that doesn't help.
In my custom field, I have three text fields:
private final TextField part1 = new TextField();
private final TextField part2 = new TextField();
private final TextField part3 = new TextField();
I'm adding a focus listener to this
and each part using this line:
Stream.of(this, part1, part2, part3).forEach(c -> c.addFocusListener(event -> this.focused = true));
Commenting out that line makes the error go away.
When I hover over the c
lambda parameter, IntelliJ IDEA shows its type:
com.vaadin.flow.component.AbstractField<? extends com.vaadin.flow.component.AbstractField<?, ?> & com.vaadin.flow.component.Focusable<? extends com.vaadin.flow.component.AbstractField<?, ?> & com.vaadin.flow.component.Focusable<?> & com.vaadin.flow.component.shared.InputField<? extends com.vaadin.flow.component.AbstractField.ComponentValueChangeEvent<? extends com.vaadin.flow.component.AbstractField<?, ?> & com.vaadin.flow.component.Focusable<?> & com.vaadin.flow.component.shared.InputField<?, ?> & com.vaadin.flow.component.HasTheme & com.vaadin.flow.component.shared.HasValidationProperties, String>, String> & com.vaadin.flow.component.HasTheme & com.vaadin.flow.component.shared.HasValidationProperties> & com.vaadin.flow.component.shared.InputField<? extends com.vaadin.flow.component.AbstractField.ComponentValueChangeEvent<? extends com.vaadin.flow.component.AbstractField<?, ?> & com.vaadin.flow.component.Focusable<?> & com.vaadin.flow.component.shared.InputField<?, ?> & com.vaadin.flow.component.HasTheme & com.vaadin.flow.component.shared.HasValidationProperties, String>, String> & com.vaadin.flow.component.HasTheme & com.vaadin.flow.component.shared.HasValidationProperties, String> & com.vaadin.flow.component.Focusable<? extends com.vaadin.flow.component.AbstractField<?, ?> & com.vaadin.flow.component.Focusable<?> & com.vaadin.flow.component.shared.InputField<? extends com.vaadin.flow.component.AbstractField.ComponentValueChangeEvent<? extends com.vaadin.flow.component.AbstractField<?, ?> & com.vaadin.flow.component.Focusable<?> & com.vaadin.flow.component.shared.InputField<?, ?> & com.vaadin.flow.component.HasTheme & com.vaadin.flow.component.shared.HasValidationProperties, String>, String> & com.vaadin.flow.component.HasTheme & com.vaadin.flow.component.shared.HasValidationProperties> & com.vaadin.flow.component.shared.InputField<? extends com.vaadin.flow.component.AbstractField.ComponentValueChangeEvent<? extends com.vaadin.flow.component.AbstractField<?, ?> & com.vaadin.flow.component.Focusable<?> & com.vaadin.flow.component.shared.InputField<?, ?> & com.vaadin.flow.component.HasTheme & com.vaadin.flow.component.shared.HasValidationProperties, String>, String> & com.vaadin.flow.component.HasTheme & com.vaadin.flow.component.shared.HasValidationProperties c
I can just add the focus listerens to this
and the parts separately:
this.addFocusListener(event -> this.focused = true);
Stream.of(part1, part2, part3).forEach(c ->
c.addFocusListener(event -> this.focused = true));
Or I can first assign the Stream
to a simpler type instead of the enormous inferred type:
Stream<Focusable<?>> stream = Stream.of(this, part1, part2, part3);
stream.forEach(c -> c.addFocusListener(event -> this.focused = true));
Or just cast this
first:
Stream.of((Focusable<?>)this, part1, part2, part3).forEach(c -> c.addFocusListener(event -> this.focused = true));
But probably the most idiomatic way without creating extra variables, is specifying the type when calling the static Stream.of
method:
Stream.<Focusable<?>>of(this, part1, part2, part3).forEach(c -> c.addFocusListener(event -> this.focused = true));
In any case, a Java generics / type inference issue, not a Vaadin issue.