Browse Source

Correct serializable issues and test that components can be serialized

Change-Id: Iac8f0f48806c0a7c3030bd406e2e533104f26753
tags/8.0.0.alpha6
Leif Åstrand 7 years ago
parent
commit
3f37f893cb
25 changed files with 402 additions and 137 deletions
  1. 11
    10
      server/src/main/java/com/vaadin/data/BeanBinder.java
  2. 34
    27
      server/src/main/java/com/vaadin/data/Binder.java
  3. 3
    1
      server/src/main/java/com/vaadin/data/Validator.java
  4. 8
    5
      server/src/main/java/com/vaadin/data/util/converter/Converter.java
  5. 2
    2
      server/src/main/java/com/vaadin/data/validator/AbstractValidator.java
  6. 38
    0
      server/src/main/java/com/vaadin/server/SerializableBiConsumer.java
  7. 49
    0
      server/src/main/java/com/vaadin/server/SerializableComparator.java
  8. 46
    0
      server/src/main/java/com/vaadin/server/SerializableFunction.java
  9. 32
    0
      server/src/main/java/com/vaadin/server/SerializablePredicate.java
  10. 6
    5
      server/src/main/java/com/vaadin/server/data/BackEndDataSource.java
  11. 3
    2
      server/src/main/java/com/vaadin/server/data/DataCommunicator.java
  12. 8
    6
      server/src/main/java/com/vaadin/ui/AbstractMultiSelect.java
  13. 4
    3
      server/src/main/java/com/vaadin/ui/CheckBoxGroup.java
  14. 29
    15
      server/src/main/java/com/vaadin/ui/Grid.java
  15. 2
    4
      server/src/main/java/com/vaadin/ui/IconGenerator.java
  16. 2
    3
      server/src/main/java/com/vaadin/ui/ItemCaptionGenerator.java
  17. 5
    4
      server/src/main/java/com/vaadin/ui/RadioButtonGroup.java
  18. 2
    3
      server/src/main/java/com/vaadin/ui/StyleGenerator.java
  19. 3
    2
      server/src/test/java/com/vaadin/data/BinderConverterValidatorTest.java
  20. 4
    4
      server/src/test/java/com/vaadin/tests/data/converter/ConverterTest.java
  21. 93
    21
      server/src/test/java/com/vaadin/tests/server/ClassesSerializableTest.java
  22. 8
    10
      server/src/test/java/com/vaadin/tests/server/component/grid/GridDefaultHeaderTest.java
  23. 5
    4
      server/src/test/java/com/vaadin/tests/server/component/grid/GridHeaderFooterTest.java
  24. 3
    4
      server/src/test/java/com/vaadin/tests/server/component/grid/GridTest.java
  25. 2
    2
      uitest/src/main/java/com/vaadin/tests/components/grid/GridApplyFilterWhenScrolledDown.java

+ 11
- 10
server/src/main/java/com/vaadin/data/BeanBinder.java View File

import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Objects; import java.util.Objects;
import java.util.function.Function;
import java.util.function.Predicate;


import com.vaadin.data.util.BeanUtil; import com.vaadin.data.util.BeanUtil;
import com.vaadin.data.util.converter.Converter; import com.vaadin.data.util.converter.Converter;
import com.vaadin.data.validator.BeanValidator; import com.vaadin.data.validator.BeanValidator;
import com.vaadin.server.SerializableBiConsumer;
import com.vaadin.server.SerializableFunction;
import com.vaadin.server.SerializablePredicate;
import com.vaadin.util.ReflectTools; import com.vaadin.util.ReflectTools;


/** /**


@Override @Override
public default BeanBinding<BEAN, FIELDVALUE, TARGET> withValidator( public default BeanBinding<BEAN, FIELDVALUE, TARGET> withValidator(
Predicate<? super TARGET> predicate, String message) {
SerializablePredicate<? super TARGET> predicate,
String message) {
return (BeanBinding<BEAN, FIELDVALUE, TARGET>) Binding.super.withValidator( return (BeanBinding<BEAN, FIELDVALUE, TARGET>) Binding.super.withValidator(
predicate, message); predicate, message);
} }


@Override @Override
public default <NEWTARGET> BeanBinding<BEAN, FIELDVALUE, NEWTARGET> withConverter( public default <NEWTARGET> BeanBinding<BEAN, FIELDVALUE, NEWTARGET> withConverter(
Function<TARGET, NEWTARGET> toModel,
Function<NEWTARGET, TARGET> toPresentation) {
SerializableFunction<TARGET, NEWTARGET> toModel,
SerializableFunction<NEWTARGET, TARGET> toPresentation) {
return (BeanBinding<BEAN, FIELDVALUE, NEWTARGET>) Binding.super.withConverter( return (BeanBinding<BEAN, FIELDVALUE, NEWTARGET>) Binding.super.withConverter(
toModel, toPresentation); toModel, toPresentation);
} }


@Override @Override
public default <NEWTARGET> BeanBinding<BEAN, FIELDVALUE, NEWTARGET> withConverter( public default <NEWTARGET> BeanBinding<BEAN, FIELDVALUE, NEWTARGET> withConverter(
Function<TARGET, NEWTARGET> toModel,
Function<NEWTARGET, TARGET> toPresentation,
SerializableFunction<TARGET, NEWTARGET> toModel,
SerializableFunction<NEWTARGET, TARGET> toPresentation,
String errorMessage) { String errorMessage) {
return (BeanBinding<BEAN, FIELDVALUE, NEWTARGET>) Binding.super.withConverter( return (BeanBinding<BEAN, FIELDVALUE, NEWTARGET>) Binding.super.withConverter(
toModel, toPresentation, errorMessage); toModel, toPresentation, errorMessage);
* @throws IllegalArgumentException * @throws IllegalArgumentException
* if the property has no accessible getter * if the property has no accessible getter
* *
* @see Binding#bind(Function, java.util.function.BiConsumer)
* @see Binding#bind(SerializableFunction, SerializableBiConsumer)
*/ */
public void bind(String propertyName); public void bind(String propertyName);
} }
* @throws IllegalArgumentException * @throws IllegalArgumentException
* if the property has no accessible getter * if the property has no accessible getter
* *
* @see #bind(HasValue, java.util.function.Function,
* java.util.function.BiConsumer)
* @see #bind(HasValue, SerializableFunction, SerializableBiConsumer)
*/ */
public <FIELDVALUE> void bind(HasValue<FIELDVALUE> field, public <FIELDVALUE> void bind(HasValue<FIELDVALUE> field,
String propertyName) { String propertyName) {

+ 34
- 27
server/src/main/java/com/vaadin/data/Binder.java View File

import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors; import java.util.stream.Collectors;


import com.vaadin.data.util.converter.Converter; import com.vaadin.data.util.converter.Converter;
import com.vaadin.data.util.converter.ValueContext; import com.vaadin.data.util.converter.ValueContext;
import com.vaadin.event.EventRouter; import com.vaadin.event.EventRouter;
import com.vaadin.server.ErrorMessage; import com.vaadin.server.ErrorMessage;
import com.vaadin.server.SerializableBiConsumer;
import com.vaadin.server.SerializableFunction;
import com.vaadin.server.SerializablePredicate;
import com.vaadin.server.UserError; import com.vaadin.server.UserError;
import com.vaadin.shared.Registration; import com.vaadin.shared.Registration;
import com.vaadin.ui.AbstractComponent; import com.vaadin.ui.AbstractComponent;
* @throws IllegalStateException * @throws IllegalStateException
* if {@code bind} has already been called on this binding * if {@code bind} has already been called on this binding
*/ */
public void bind(Function<BEAN, TARGET> getter,
BiConsumer<BEAN, TARGET> setter);
public void bind(SerializableFunction<BEAN, TARGET> getter,
com.vaadin.server.SerializableBiConsumer<BEAN, TARGET> setter);


/** /**
* Adds a validator to this binding. Validators are applied, in * Adds a validator to this binding. Validators are applied, in


/** /**
* A convenience method to add a validator to this binding using the * A convenience method to add a validator to this binding using the
* {@link Validator#from(Predicate, String)} factory method.
* {@link Validator#from(SerializablePredicate, String)} factory method.
* <p> * <p>
* Validators are applied, in registration order, when the field value * Validators are applied, in registration order, when the field value
* is saved to the backing property. If any validator returns a failure, * is saved to the backing property. If any validator returns a failure,
* the property value is not updated. * the property value is not updated.
* *
* @see #withValidator(Validator) * @see #withValidator(Validator)
* @see Validator#from(Predicate, String)
* @see Validator#from(SerializablePredicate, String)
* *
* @param predicate * @param predicate
* the predicate performing validation, not null * the predicate performing validation, not null
* if {@code bind} has already been called * if {@code bind} has already been called
*/ */
public default Binding<BEAN, FIELDVALUE, TARGET> withValidator( public default Binding<BEAN, FIELDVALUE, TARGET> withValidator(
Predicate<? super TARGET> predicate, String message) {
SerializablePredicate<? super TARGET> predicate,
String message) {
return withValidator(Validator.from(predicate, message)); return withValidator(Validator.from(predicate, message));
} }


* which must match the current target data type of the binding, and a * which must match the current target data type of the binding, and a
* model type, which can be any data type and becomes the new target * model type, which can be any data type and becomes the new target
* type of the binding. When invoking * type of the binding. When invoking
* {@link #bind(Function, BiConsumer)}, the target type of the binding
* must match the getter/setter types.
* {@link #bind(SerializableFunction, SerializableBiConsumer)}, the
* target type of the binding must match the getter/setter types.
* <p> * <p>
* For instance, a {@code TextField} can be bound to an integer-typed * For instance, a {@code TextField} can be bound to an integer-typed
* property using an appropriate converter such as a * property using an appropriate converter such as a
* type, which must match the current target data type of the binding, * type, which must match the current target data type of the binding,
* and a model type, which can be any data type and becomes the new * and a model type, which can be any data type and becomes the new
* target type of the binding. When invoking * target type of the binding. When invoking
* {@link #bind(Function, BiConsumer)}, the target type of the binding
* must match the getter/setter types.
* {@link #bind(SerializableFunction, SerializableBiConsumer)}, the
* target type of the binding must match the getter/setter types.
* <p> * <p>
* For instance, a {@code TextField} can be bound to an integer-typed * For instance, a {@code TextField} can be bound to an integer-typed
* property using appropriate functions such as: * property using appropriate functions such as:
* if {@code bind} has already been called * if {@code bind} has already been called
*/ */
public default <NEWTARGET> Binding<BEAN, FIELDVALUE, NEWTARGET> withConverter( public default <NEWTARGET> Binding<BEAN, FIELDVALUE, NEWTARGET> withConverter(
Function<TARGET, NEWTARGET> toModel,
Function<NEWTARGET, TARGET> toPresentation) {
SerializableFunction<TARGET, NEWTARGET> toModel,
SerializableFunction<NEWTARGET, TARGET> toPresentation) {
return withConverter(Converter.from(toModel, toPresentation, return withConverter(Converter.from(toModel, toPresentation,
exception -> exception.getMessage())); exception -> exception.getMessage()));
} }
* type, which must match the current target data type of the binding, * type, which must match the current target data type of the binding,
* and a model type, which can be any data type and becomes the new * and a model type, which can be any data type and becomes the new
* target type of the binding. When invoking * target type of the binding. When invoking
* {@link #bind(Function, BiConsumer)}, the target type of the binding
* must match the getter/setter types.
* {@link #bind(SerializableFunction, SerializableBiConsumer)}, the
* target type of the binding must match the getter/setter types.
* <p> * <p>
* For instance, a {@code TextField} can be bound to an integer-typed * For instance, a {@code TextField} can be bound to an integer-typed
* property using appropriate functions such as: * property using appropriate functions such as:
* if {@code bind} has already been called * if {@code bind} has already been called
*/ */
public default <NEWTARGET> Binding<BEAN, FIELDVALUE, NEWTARGET> withConverter( public default <NEWTARGET> Binding<BEAN, FIELDVALUE, NEWTARGET> withConverter(
Function<TARGET, NEWTARGET> toModel,
Function<NEWTARGET, TARGET> toPresentation,
SerializableFunction<TARGET, NEWTARGET> toModel,
SerializableFunction<NEWTARGET, TARGET> toPresentation,
String errorMessage) { String errorMessage) {
return withConverter(Converter.from(toModel, toPresentation, return withConverter(Converter.from(toModel, toPresentation,
exception -> errorMessage)); exception -> errorMessage));
private ValidationStatusHandler statusHandler; private ValidationStatusHandler statusHandler;
private boolean isStatusHandlerChanged; private boolean isStatusHandlerChanged;


private Function<BEAN, TARGET> getter;
private BiConsumer<BEAN, TARGET> setter;
private SerializableFunction<BEAN, TARGET> getter;
private SerializableBiConsumer<BEAN, TARGET> setter;


/** /**
* Contains all converters and validators chained together in the * Contains all converters and validators chained together in the
} }


@Override @Override
public void bind(Function<BEAN, TARGET> getter,
BiConsumer<BEAN, TARGET> setter) {
public void bind(SerializableFunction<BEAN, TARGET> getter,
SerializableBiConsumer<BEAN, TARGET> setter) {
checkUnbound(); checkUnbound();
Objects.requireNonNull(getter, "getter cannot be null"); Objects.requireNonNull(getter, "getter cannot be null");




/** /**
* Creates a new binding for the given field. The returned binding may be * Creates a new binding for the given field. The returned binding may be
* further configured before invoking
* further configured before invoking <<<<<<< Upstream, based on master
* {@link Binding#bind(Function, BiConsumer) Binding.bind} which completes * {@link Binding#bind(Function, BiConsumer) Binding.bind} which completes
* the binding. Until {@code Binding.bind} is called, the binding has no * the binding. Until {@code Binding.bind} is called, the binding has no
* effect. * effect.
* automatically change {@code null} to a null representation provided by * automatically change {@code null} to a null representation provided by
* {@link HasValue#getEmptyValue()}. This conversion is one-way only, if you * {@link HasValue#getEmptyValue()}. This conversion is one-way only, if you
* want to have a two-way mapping back to {@code null}, use * want to have a two-way mapping back to {@code null}, use
* {@link Binding#withNullRepresentation(Object))}.
* {@link Binding#withNullRepresentation(Object))}. =======
* {@link Binding#bind(SerializableFunction, SerializableBiConsumer)
* Binding.bind} which completes the binding. Until {@code Binding.bind} is
* called, the binding has no effect. >>>>>>> 7d541b5 Correct serializable
* issues and test that components can be serialized
* *
* @param <FIELDVALUE> * @param <FIELDVALUE>
* the value type of the field * the value type of the field
* the field to be bound, not null * the field to be bound, not null
* @return the new binding * @return the new binding
* *
* @see #bind(HasValue, Function, BiConsumer)
* @see #bind(HasValue, SerializableFunction, SerializableBiConsumer)
*/ */
public <FIELDVALUE> Binding<BEAN, FIELDVALUE, FIELDVALUE> forField( public <FIELDVALUE> Binding<BEAN, FIELDVALUE, FIELDVALUE> forField(
HasValue<FIELDVALUE> field) { HasValue<FIELDVALUE> field) {
* if read-only * if read-only
*/ */
public <FIELDVALUE> void bind(HasValue<FIELDVALUE> field, public <FIELDVALUE> void bind(HasValue<FIELDVALUE> field,
Function<BEAN, FIELDVALUE> getter,
BiConsumer<BEAN, FIELDVALUE> setter) {
SerializableFunction<BEAN, FIELDVALUE> getter,
SerializableBiConsumer<BEAN, FIELDVALUE> setter) {
forField(field).bind(getter, setter); forField(field).bind(getter, setter);
} }


* <li>{@link #load(Object)} is called * <li>{@link #load(Object)} is called
* <li>{@link #bind(Object)} is called * <li>{@link #bind(Object)} is called
* <li>{@link #unbind(Object)} is called * <li>{@link #unbind(Object)} is called
* <li>{@link Binding#bind(Function, BiConsumer)} is called
* <li>{@link Binding#bind(SerializableFunction, SerializableBiConsumer)} is
* called
* <li>{@link Binder#validate()} or {@link Binding#validate()} is called * <li>{@link Binder#validate()} or {@link Binding#validate()} is called
* </ul> * </ul>
* *

+ 3
- 1
server/src/main/java/com/vaadin/data/Validator.java View File

import java.util.function.Function; import java.util.function.Function;
import java.util.function.Predicate; import java.util.function.Predicate;


import com.vaadin.server.SerializablePredicate;

/** /**
* A functional interface for validating user input or other potentially invalid * A functional interface for validating user input or other potentially invalid
* data. When a validator instance is applied to a value of the corresponding * data. When a validator instance is applied to a value of the corresponding
* the message returned if validation fails, not null * the message returned if validation fails, not null
* @return the new validator using the function * @return the new validator using the function
*/ */
public static <T> Validator<T> from(Predicate<T> guard,
public static <T> Validator<T> from(SerializablePredicate<T> guard,
String errorMessage) { String errorMessage) {
Objects.requireNonNull(guard, "guard cannot be null"); Objects.requireNonNull(guard, "guard cannot be null");
Objects.requireNonNull(errorMessage, "errorMessage cannot be null"); Objects.requireNonNull(errorMessage, "errorMessage cannot be null");

+ 8
- 5
server/src/main/java/com/vaadin/data/util/converter/Converter.java View File



import com.vaadin.data.Binder.Binding; import com.vaadin.data.Binder.Binding;
import com.vaadin.data.Result; import com.vaadin.data.Result;
import com.vaadin.server.SerializableFunction;


/** /**
* Interface that implements conversion between a model and a presentation type. * Interface that implements conversion between a model and a presentation type.
* @see Result * @see Result
* @see Function * @see Function
*/ */
public static <P, M> Converter<P, M> from(Function<P, M> toModel,
Function<M, P> toPresentation,
Function<Exception, String> onError) {
public static <P, M> Converter<P, M> from(
SerializableFunction<P, M> toModel,
SerializableFunction<M, P> toPresentation,
SerializableFunction<Exception, String> onError) {


return from(val -> Result.of(() -> toModel.apply(val), onError), return from(val -> Result.of(() -> toModel.apply(val), onError),
toPresentation); toPresentation);
* *
* @see Function * @see Function
*/ */
public static <P, M> Converter<P, M> from(Function<P, Result<M>> toModel,
Function<M, P> toPresentation) {
public static <P, M> Converter<P, M> from(
SerializableFunction<P, Result<M>> toModel,
SerializableFunction<M, P> toPresentation) {
return new Converter<P, M>() { return new Converter<P, M>() {


@Override @Override

+ 2
- 2
server/src/main/java/com/vaadin/data/validator/AbstractValidator.java View File

package com.vaadin.data.validator; package com.vaadin.data.validator;


import java.util.Objects; import java.util.Objects;
import java.util.function.Function;


import com.vaadin.data.Result; import com.vaadin.data.Result;
import com.vaadin.data.Validator; import com.vaadin.data.Validator;
import com.vaadin.server.SerializableFunction;


/** /**
* An abstract base class for typed validators. * An abstract base class for typed validators.
*/ */
public abstract class AbstractValidator<T> implements Validator<T> { public abstract class AbstractValidator<T> implements Validator<T> {


private Function<T, String> messageProvider;
private SerializableFunction<T, String> messageProvider;


/** /**
* Constructs a validator with the given error message. The substring "{0}" * Constructs a validator with the given error message. The substring "{0}"

+ 38
- 0
server/src/main/java/com/vaadin/server/SerializableBiConsumer.java View File

/*
* Copyright 2000-2016 Vaadin Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.vaadin.server;

import java.io.Serializable;
import java.util.function.BiConsumer;

/**
* A {@link BiConsumer} that is also {@link Serializable}.
*
* @see {@link BiConsumer}
* @param <T>
* the type of the first argument to the operation
* @param <U>
* the type of the second argument to the operation
*
* @since 8.0
* @author Vaadin Ltd
*
*/
@FunctionalInterface
public interface SerializableBiConsumer<T, U>
extends BiConsumer<T, U>, Serializable {
// Only method inherited from BiConsumer
}

+ 49
- 0
server/src/main/java/com/vaadin/server/SerializableComparator.java View File

/*
* Copyright 2000-2016 Vaadin Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.vaadin.server;

import java.io.Serializable;
import java.util.Comparator;

/**
* A {@link Comparator} that is also {@link Serializable}.
*
* @author Vaadin Ltd
* @param <T>
* the type of objects that may be compared by this comparator
* @since 8.0
*
*/
@FunctionalInterface
public interface SerializableComparator<T> extends Comparator<T>, Serializable {

/**
* Returns a {@link SerializableComparator} instance which delegates its
* logic to the provided {@code comparator}.
*
* @param comparator
* comparator to convert
* @param <T>
* the type of objects that may be compared by this comparator
* @param <C>
* the comparator type
* @return a SerializableComparator view of the {@code comparator}
*/
static <C extends Comparator<T> & Serializable, T> SerializableComparator<T> asInstance(
C comparator) {
return (arg1, arg2) -> comparator.compare(arg1, arg2);
}
}

+ 46
- 0
server/src/main/java/com/vaadin/server/SerializableFunction.java View File

/*
* Copyright 2000-2016 Vaadin Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.vaadin.server;

import java.io.Serializable;
import java.util.function.Function;

/**
* A {@link Function} that is also {@link Serializable}.
*
* @see Function
* @author Vaadin Ltd
* @since 8.0
* @param <T>
* the type of the input to the function
* @param <R>
* the type of the result of the function
*/
@FunctionalInterface
public interface SerializableFunction<T, R>
extends Function<T, R>, Serializable {
/**
* Returns a function that always returns its input argument.
*
* @param <T>
* the type of the input and output objects to the function
* @return a function that always returns its input argument
*/
static <T> SerializableFunction<T, T> identity() {
return t -> t;
}

}

+ 32
- 0
server/src/main/java/com/vaadin/server/SerializablePredicate.java View File

/*
* Copyright 2000-2016 Vaadin Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.vaadin.server;

import java.io.Serializable;
import java.util.function.Predicate;

/**
* A {@link Predicate} that is also {@link Serializable}.
*
* @author Vaadin Ltd
* @since 8.0
* @param <T>
* the type of the input to the predicate
*
*/
public interface SerializablePredicate<T> extends Predicate<T>, Serializable {
// Only method inherited from Function
}

+ 6
- 5
server/src/main/java/com/vaadin/server/data/BackEndDataSource.java View File

import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Stream; import java.util.stream.Stream;


import com.vaadin.server.SerializableFunction;

/** /**
* A {@link DataSource} for any back end. * A {@link DataSource} for any back end.
* *
*/ */
public class BackEndDataSource<T> extends AbstractDataSource<T> { public class BackEndDataSource<T> extends AbstractDataSource<T> {


private Function<Query, Stream<T>> request;
private Function<Query, Integer> sizeCallback;
private SerializableFunction<Query, Stream<T>> request;
private SerializableFunction<Query, Integer> sizeCallback;


/** /**
* Constructs a new DataSource to request data from an arbitrary back end * Constructs a new DataSource to request data from an arbitrary back end
* @param sizeCallback * @param sizeCallback
* function that return the amount of data in back end for query * function that return the amount of data in back end for query
*/ */
public BackEndDataSource(Function<Query, Stream<T>> request,
Function<Query, Integer> sizeCallback) {
public BackEndDataSource(SerializableFunction<Query, Stream<T>> request,
SerializableFunction<Query, Integer> sizeCallback) {
Objects.requireNonNull(request, "Request function can't be null"); Objects.requireNonNull(request, "Request function can't be null");
Objects.requireNonNull(sizeCallback, "Size callback can't be null"); Objects.requireNonNull(sizeCallback, "Size callback can't be null");
this.request = request; this.request = request;

+ 3
- 2
server/src/main/java/com/vaadin/server/data/DataCommunicator.java View File



import com.vaadin.server.AbstractExtension; import com.vaadin.server.AbstractExtension;
import com.vaadin.server.KeyMapper; import com.vaadin.server.KeyMapper;
import com.vaadin.server.SerializablePredicate;
import com.vaadin.shared.Range; import com.vaadin.shared.Range;
import com.vaadin.shared.Registration; import com.vaadin.shared.Registration;
import com.vaadin.shared.data.DataCommunicatorClientRpc; import com.vaadin.shared.data.DataCommunicatorClientRpc;
private Range pushRows = Range.withLength(0, 40); private Range pushRows = Range.withLength(0, 40);


private Comparator<T> inMemorySorting; private Comparator<T> inMemorySorting;
private Predicate<T> inMemoryFilter;
private SerializablePredicate<T> inMemoryFilter;
private List<SortOrder<String>> backEndSorting = new ArrayList<>(); private List<SortOrder<String>> backEndSorting = new ArrayList<>();
private DataCommunicatorClientRpc rpc; private DataCommunicatorClientRpc rpc;


* @param predicate * @param predicate
* predicate used to filter data * predicate used to filter data
*/ */
public void setInMemoryFilter(Predicate<T> predicate) {
public void setInMemoryFilter(SerializablePredicate<T> predicate) {
inMemoryFilter = predicate; inMemoryFilter = predicate;
reset(); reset();
} }

+ 8
- 6
server/src/main/java/com/vaadin/ui/AbstractMultiSelect.java View File

import com.vaadin.event.selection.MultiSelectionListener; import com.vaadin.event.selection.MultiSelectionListener;
import com.vaadin.server.Resource; import com.vaadin.server.Resource;
import com.vaadin.server.ResourceReference; import com.vaadin.server.ResourceReference;
import com.vaadin.server.SerializablePredicate;
import com.vaadin.server.data.DataGenerator; import com.vaadin.server.data.DataGenerator;
import com.vaadin.shared.Registration; import com.vaadin.shared.Registration;
import com.vaadin.shared.data.selection.MultiSelectServerRpc; import com.vaadin.shared.data.selection.MultiSelectServerRpc;
* The item enabled status provider. It is up to the implementing class to * The item enabled status provider. It is up to the implementing class to
* support this or not. * support this or not.
*/ */
private Predicate<T> itemEnabledProvider = item -> true;
private SerializablePredicate<T> itemEnabledProvider = item -> true;


/** /**
* Creates a new multi select with an empty data source. * Creates a new multi select with an empty data source.
* Returns the item enabled provider for this multiselect. * Returns the item enabled provider for this multiselect.
* <p> * <p>
* <em>Implementation note:</em> Override this method and * <em>Implementation note:</em> Override this method and
* {@link #setItemEnabledProvider(Predicate)} as {@code public} and invoke
* {@code super} methods to support this feature in the multiselect
* component.
* {@link #setItemEnabledProvider(SerializablePredicate)} as {@code public}
* and invoke {@code super} methods to support this feature in the
* multiselect component.
* *
* @return the item enabled provider, not {@code null} * @return the item enabled provider, not {@code null}
* @see #setItemEnabledProvider(Predicate) * @see #setItemEnabledProvider(Predicate)
*/ */
protected Predicate<T> getItemEnabledProvider() {
protected SerializablePredicate<T> getItemEnabledProvider() {
return itemEnabledProvider; return itemEnabledProvider;
} }


* @param itemEnabledProvider * @param itemEnabledProvider
* the item enabled provider to set, not {@code null} * the item enabled provider to set, not {@code null}
*/ */
protected void setItemEnabledProvider(Predicate<T> itemEnabledProvider) {
protected void setItemEnabledProvider(
SerializablePredicate<T> itemEnabledProvider) {
Objects.requireNonNull(itemEnabledProvider); Objects.requireNonNull(itemEnabledProvider);
this.itemEnabledProvider = itemEnabledProvider; this.itemEnabledProvider = itemEnabledProvider;
} }

+ 4
- 3
server/src/main/java/com/vaadin/ui/CheckBoxGroup.java View File

package com.vaadin.ui; package com.vaadin.ui;


import java.util.Collection; import java.util.Collection;
import java.util.function.Predicate;


import com.vaadin.data.Listing; import com.vaadin.data.Listing;
import com.vaadin.server.SerializablePredicate;
import com.vaadin.server.data.DataSource; import com.vaadin.server.data.DataSource;
import com.vaadin.shared.ui.optiongroup.CheckBoxGroupState; import com.vaadin.shared.ui.optiongroup.CheckBoxGroupState;


} }


@Override @Override
public Predicate<T> getItemEnabledProvider() {
public SerializablePredicate<T> getItemEnabledProvider() {
return super.getItemEnabledProvider(); return super.getItemEnabledProvider();
} }


@Override @Override
public void setItemEnabledProvider(Predicate<T> itemEnabledProvider) {
public void setItemEnabledProvider(
SerializablePredicate<T> itemEnabledProvider) {
super.setItemEnabledProvider(itemEnabledProvider); super.setItemEnabledProvider(itemEnabledProvider);
} }
} }

+ 29
- 15
server/src/main/java/com/vaadin/ui/Grid.java View File

import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.function.BinaryOperator;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import com.vaadin.event.EventListener; import com.vaadin.event.EventListener;
import com.vaadin.server.EncodeResult; import com.vaadin.server.EncodeResult;
import com.vaadin.server.JsonCodec; import com.vaadin.server.JsonCodec;
import com.vaadin.server.SerializableComparator;
import com.vaadin.server.SerializableFunction;
import com.vaadin.server.data.SortOrder; import com.vaadin.server.data.SortOrder;
import com.vaadin.shared.MouseEventDetails; import com.vaadin.shared.MouseEventDetails;
import com.vaadin.shared.Registration; import com.vaadin.shared.Registration;
*/ */
@FunctionalInterface @FunctionalInterface
public interface DescriptionGenerator<T> public interface DescriptionGenerator<T>
extends Function<T, String>, Serializable {
extends SerializableFunction<T, String> {
} }


/** /**


// Set sort orders // Set sort orders
// In-memory comparator // In-memory comparator
Comparator<T> comparator = sortOrder.stream()
BinaryOperator<SerializableComparator<T>> operator = (comparator1,
comparator2) -> SerializableComparator.asInstance(
(Comparator<T> & Serializable) comparator1
.thenComparing(comparator2));
SerializableComparator<T> comparator = sortOrder.stream()
.map(order -> order.getSorted() .map(order -> order.getSorted()
.getComparator(order.getDirection())) .getComparator(order.getDirection()))
.reduce((x, y) -> 0, Comparator::thenComparing);
.reduce((x, y) -> 0, operator);
getDataCommunicator().setInMemorySorting(comparator); getDataCommunicator().setInMemorySorting(comparator);


// Back-end sort properties // Back-end sort properties
*/ */
public static class Column<T, V> extends AbstractGridExtension<T> { public static class Column<T, V> extends AbstractGridExtension<T> {


private final Function<T, ? extends V> valueProvider;
private final SerializableFunction<T, ? extends V> valueProvider;


private Function<SortDirection, Stream<SortOrder<String>>> sortOrderProvider;
private Comparator<T> comparator;
private SerializableFunction<SortDirection, Stream<SortOrder<String>>> sortOrderProvider;
private SerializableComparator<T> comparator;
private StyleGenerator<T> styleGenerator = item -> null; private StyleGenerator<T> styleGenerator = item -> null;
private DescriptionGenerator<T> descriptionGenerator; private DescriptionGenerator<T> descriptionGenerator;


* @param renderer * @param renderer
* the type of value * the type of value
*/ */
protected Column(String caption, Function<T, ? extends V> valueProvider,
protected Column(String caption,
SerializableFunction<T, ? extends V> valueProvider,
Renderer<V> renderer) { Renderer<V> renderer) {
Objects.requireNonNull(caption, "Header caption can't be null"); Objects.requireNonNull(caption, "Header caption can't be null");
Objects.requireNonNull(valueProvider, Objects.requireNonNull(valueProvider,
* the comparator to use when sorting data in this column * the comparator to use when sorting data in this column
* @return this column * @return this column
*/ */
public Column<T, V> setComparator(Comparator<T> comparator) {
public Column<T, V> setComparator(
SerializableComparator<T> comparator) {
Objects.requireNonNull(comparator, "Comparator can't be null"); Objects.requireNonNull(comparator, "Comparator can't be null");
this.comparator = comparator; this.comparator = comparator;
return this; return this;
* the direction this column is sorted by * the direction this column is sorted by
* @return comparator for this column * @return comparator for this column
*/ */
public Comparator<T> getComparator(SortDirection sortDirection) {
public SerializableComparator<T> getComparator(
SortDirection sortDirection) {
Objects.requireNonNull(comparator, Objects.requireNonNull(comparator,
"No comparator defined for sorted column."); "No comparator defined for sorted column.");
boolean reverse = sortDirection != SortDirection.ASCENDING; boolean reverse = sortDirection != SortDirection.ASCENDING;
return reverse ? comparator.reversed() : comparator;
return reverse ? (t1, t2) -> comparator.reversed().compare(t1, t2)
: comparator;
} }


/** /**
* @return this column * @return this column
*/ */
public Column<T, V> setSortOrderProvider( public Column<T, V> setSortOrderProvider(
Function<SortDirection, Stream<SortOrder<String>>> provider) {
SerializableFunction<SortDirection, Stream<SortOrder<String>>> provider) {
Objects.requireNonNull(provider, Objects.requireNonNull(provider,
"Sort order provider can't be null"); "Sort order provider can't be null");
sortOrderProvider = provider; sortOrderProvider = provider;
* @see {@link AbstractRenderer} * @see {@link AbstractRenderer}
*/ */
public <V> Column<T, V> addColumn(String identifier, public <V> Column<T, V> addColumn(String identifier,
Function<T, ? extends V> valueProvider,
SerializableFunction<T, ? extends V> valueProvider,
AbstractRenderer<? super T, V> renderer) AbstractRenderer<? super T, V> renderer)
throws IllegalArgumentException { throws IllegalArgumentException {
if (columnKeys.containsKey(identifier)) { if (columnKeys.containsKey(identifier)) {
* if the same identifier is used for multiple columns * if the same identifier is used for multiple columns
*/ */
public Column<T, String> addColumn(String identifier, public Column<T, String> addColumn(String identifier,
Function<T, String> valueProvider) {
SerializableFunction<T, String> valueProvider) {
return addColumn(identifier, valueProvider, new TextRenderer()); return addColumn(identifier, valueProvider, new TextRenderer());
} }


* *
* @return the new column * @return the new column
*/ */
public Column<T, String> addColumn(Function<T, String> valueProvider) {
public Column<T, String> addColumn(
SerializableFunction<T, String> valueProvider) {
return addColumn(getGeneratedIdentifier(), valueProvider, return addColumn(getGeneratedIdentifier(), valueProvider,
new TextRenderer()); new TextRenderer());
} }
* *
* @see {@link AbstractRenderer} * @see {@link AbstractRenderer}
*/ */
public <V> Column<T, V> addColumn(Function<T, ? extends V> valueProvider,
public <V> Column<T, V> addColumn(
SerializableFunction<T, ? extends V> valueProvider,
AbstractRenderer<? super T, V> renderer) { AbstractRenderer<? super T, V> renderer) {
return addColumn(getGeneratedIdentifier(), valueProvider, renderer); return addColumn(getGeneratedIdentifier(), valueProvider, renderer);
} }
boolean userOriginated) { boolean userOriginated) {
fireEvent(new ColumnResizeEvent(this, column, userOriginated)); fireEvent(new ColumnResizeEvent(this, column, userOriginated));
} }

} }

+ 2
- 4
server/src/main/java/com/vaadin/ui/IconGenerator.java View File

*/ */
package com.vaadin.ui; package com.vaadin.ui;


import java.io.Serializable;
import java.util.function.Function;

import com.vaadin.server.Resource; import com.vaadin.server.Resource;
import com.vaadin.server.SerializableFunction;


/** /**
* A callback interface for generating icons for an item. * A callback interface for generating icons for an item.
* item type for which the icon is generated * item type for which the icon is generated
*/ */
@FunctionalInterface @FunctionalInterface
public interface IconGenerator<T> extends Function<T, Resource>, Serializable {
public interface IconGenerator<T> extends SerializableFunction<T, Resource> {


/** /**
* Gets an icon resource for the {@code item}. * Gets an icon resource for the {@code item}.

+ 2
- 3
server/src/main/java/com/vaadin/ui/ItemCaptionGenerator.java View File

*/ */
package com.vaadin.ui; package com.vaadin.ui;


import java.io.Serializable;
import java.util.function.Function;
import com.vaadin.server.SerializableFunction;


/** /**
* {@link ItemCaptionGenerator} can be used to customize the string shown to the * {@link ItemCaptionGenerator} can be used to customize the string shown to the
*/ */
@FunctionalInterface @FunctionalInterface
public interface ItemCaptionGenerator<T> public interface ItemCaptionGenerator<T>
extends Function<T, String>, Serializable {
extends SerializableFunction<T, String> {


/** /**
* Gets a caption for the {@code item}. * Gets a caption for the {@code item}.

+ 5
- 4
server/src/main/java/com/vaadin/ui/RadioButtonGroup.java View File



import java.util.Collection; import java.util.Collection;
import java.util.Objects; import java.util.Objects;
import java.util.function.Predicate;


import com.vaadin.data.Listing; import com.vaadin.data.Listing;
import com.vaadin.server.Resource; import com.vaadin.server.Resource;
import com.vaadin.server.ResourceReference; import com.vaadin.server.ResourceReference;
import com.vaadin.server.SerializablePredicate;
import com.vaadin.server.data.DataGenerator; import com.vaadin.server.data.DataGenerator;
import com.vaadin.server.data.DataSource; import com.vaadin.server.data.DataSource;
import com.vaadin.shared.ui.ListingJsonConstants; import com.vaadin.shared.ui.ListingJsonConstants;


private ItemCaptionGenerator<T> itemCaptionGenerator = String::valueOf; private ItemCaptionGenerator<T> itemCaptionGenerator = String::valueOf;


private Predicate<T> itemEnabledProvider = item -> true;
private SerializablePredicate<T> itemEnabledProvider = item -> true;


/** /**
* Constructs a new RadioButtonGroup with caption. * Constructs a new RadioButtonGroup with caption.
* @return the item enabled predicate * @return the item enabled predicate
* @see #setItemEnabledProvider * @see #setItemEnabledProvider
*/ */
public Predicate<T> getItemEnabledProvider() {
public SerializablePredicate<T> getItemEnabledProvider() {
return itemEnabledProvider; return itemEnabledProvider;
} }


* @param itemEnabledProvider * @param itemEnabledProvider
* the item enable predicate, not null * the item enable predicate, not null
*/ */
public void setItemEnabledProvider(Predicate<T> itemEnabledProvider) {
public void setItemEnabledProvider(
SerializablePredicate<T> itemEnabledProvider) {
Objects.requireNonNull(itemEnabledProvider); Objects.requireNonNull(itemEnabledProvider);
this.itemEnabledProvider = itemEnabledProvider; this.itemEnabledProvider = itemEnabledProvider;
} }

+ 2
- 3
server/src/main/java/com/vaadin/ui/StyleGenerator.java View File

*/ */
package com.vaadin.ui; package com.vaadin.ui;


import java.io.Serializable;
import java.util.function.Function;
import com.vaadin.server.SerializableFunction;


/** /**
* A callback interface for generating custom CSS class names for items. * A callback interface for generating custom CSS class names for items.
* @author Vaadin Ltd * @author Vaadin Ltd
*/ */
@FunctionalInterface @FunctionalInterface
public interface StyleGenerator<T> extends Function<T, String>, Serializable {
public interface StyleGenerator<T> extends SerializableFunction<T, String> {


/** /**
* Gets a class name for the {@code item}. * Gets a class name for the {@code item}.

+ 3
- 2
server/src/test/java/com/vaadin/data/BinderConverterValidatorTest.java View File



import java.util.List; import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Predicate;


import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import com.vaadin.data.validator.NotEmptyValidator; import com.vaadin.data.validator.NotEmptyValidator;
import com.vaadin.server.AbstractErrorMessage; import com.vaadin.server.AbstractErrorMessage;
import com.vaadin.server.ErrorMessage; import com.vaadin.server.ErrorMessage;
import com.vaadin.server.SerializablePredicate;
import com.vaadin.server.UserError; import com.vaadin.server.UserError;
import com.vaadin.tests.data.bean.Person; import com.vaadin.tests.data.bean.Person;
import com.vaadin.ui.Label; import com.vaadin.ui.Label;
@Test @Test
public void binderLoad_withCrossFieldValidation_clearsErrors() { public void binderLoad_withCrossFieldValidation_clearsErrors() {
TextField lastNameField = new TextField(); TextField lastNameField = new TextField();
final Predicate<String> lengthPredicate = v -> v.length() > 2;
final SerializablePredicate<String> lengthPredicate = v -> v
.length() > 2;


Binding<Person, String, String> firstNameBinding = binder Binding<Person, String, String> firstNameBinding = binder
.forField(nameField).withValidator(lengthPredicate, "length"); .forField(nameField).withValidator(lengthPredicate, "length");

+ 4
- 4
server/src/test/java/com/vaadin/tests/data/converter/ConverterTest.java View File

package com.vaadin.tests.data.converter; package com.vaadin.tests.data.converter;


import java.util.function.Function;

import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;


import com.vaadin.data.Result; import com.vaadin.data.Result;
import com.vaadin.data.util.converter.Converter; import com.vaadin.data.util.converter.Converter;
import com.vaadin.data.util.converter.ValueContext; import com.vaadin.data.util.converter.ValueContext;
import com.vaadin.server.SerializableFunction;


public class ConverterTest { public class ConverterTest {


Function<String, Result<String>> toModel = presentation -> {
SerializableFunction<String, Result<String>> toModel = presentation -> {
if (presentation.startsWith("presentation-")) { if (presentation.startsWith("presentation-")) {
return Result.ok(presentation.substring("presentation-".length())); return Result.ok(presentation.substring("presentation-".length()));
} else { } else {
} }
}; };


Function<String, String> toPresentation = model -> "presentation-" + model;
SerializableFunction<String, String> toPresentation = model -> "presentation-"
+ model;


Converter<String, String> converter = Converter.from(toModel, Converter<String, String> converter = Converter.from(toModel,
toPresentation); toPresentation);

+ 93
- 21
server/src/test/java/com/vaadin/tests/server/ClassesSerializableTest.java View File

package com.vaadin.tests.server; package com.vaadin.tests.server;


import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable; import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.jar.JarEntry; import java.util.jar.JarEntry;
import java.util.jar.JarFile; import java.util.jar.JarFile;
import java.util.stream.Collectors;
import java.util.stream.Stream;


import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;


import com.vaadin.ui.Component;

public class ClassesSerializableTest { public class ClassesSerializableTest {


/** /**
classes.addAll(findServerClasses(location)); classes.addAll(findServerClasses(location));
} }


ArrayList<Field> nonSerializableFunctionFields = new ArrayList<>();

ArrayList<Class<?>> nonSerializableClasses = new ArrayList<>(); ArrayList<Class<?>> nonSerializableClasses = new ArrayList<>();
for (String className : classes) { for (String className : classes) {
Class<?> cls = Class.forName(className); Class<?> cls = Class.forName(className);
// Don't add classes that have a @Ignore annotation on the class
if (isTestClass(cls)) {
continue;
}

// report fields that use lambda types that won't be serializable
// (also in syntehtic classes)
Stream.of(cls.getDeclaredFields())
.filter(field -> isFunctionalType(field.getGenericType()))
.forEach(nonSerializableFunctionFields::add);

// skip annotations and synthetic classes // skip annotations and synthetic classes
if (cls.isAnnotation() || cls.isSynthetic()) { if (cls.isAnnotation() || cls.isSynthetic()) {
continue; continue;
} }
// Don't add classes that have a @Ignore annotation on the class
if (isTestClass(cls)) {
continue;

if (Component.class.isAssignableFrom(cls) && !cls.isInterface()
&& !Modifier.isAbstract(cls.getModifiers())) {
serializeAndDeserialize(cls);
} }


// report non-serializable classes and interfaces // report non-serializable classes and interfaces
// useful failure message including all non-serializable classes and // useful failure message including all non-serializable classes and
// interfaces // interfaces
if (!nonSerializableClasses.isEmpty()) { if (!nonSerializableClasses.isEmpty()) {
String nonSerializableString = "";
Iterator<Class<?>> it = nonSerializableClasses.iterator();
while (it.hasNext()) {
Class c = it.next();
nonSerializableString += ", " + c.getName();
if (c.isAnonymousClass()) {
nonSerializableString += "(super: ";
nonSerializableString += c.getSuperclass().getName();
nonSerializableString += ", interfaces: ";
for (Class i : c.getInterfaces()) {
nonSerializableString += i.getName();
nonSerializableString += ",";
}
nonSerializableString += ")";
failSerializableClasses(nonSerializableClasses);
}

if (!nonSerializableFunctionFields.isEmpty()) {
failSerializableFields(nonSerializableFunctionFields);
}
}

private void serializeAndDeserialize(Class<?> clazz)
throws IOException, ClassNotFoundException, InstantiationException,
IllegalAccessException, IllegalArgumentException,
InvocationTargetException {
Optional<Constructor<?>> defaultCtor = Stream
.of(clazz.getDeclaredConstructors())
.filter(ctor -> ctor.getParameterCount() == 0).findFirst();
if (!defaultCtor.isPresent()) {
return;
}
defaultCtor.get().setAccessible(true);
Object instance = defaultCtor.get().newInstance();
ByteArrayOutputStream bs = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(bs);
out.writeObject(instance);
byte[] data = bs.toByteArray();
ObjectInputStream in = new ObjectInputStream(
new ByteArrayInputStream(data));
in.readObject();
}

private void failSerializableFields(
ArrayList<Field> nonSerializableFunctionFields) {
String nonSerializableString = nonSerializableFunctionFields.stream()
.map(field -> String.format("%s.%s",
field.getDeclaringClass().getName(), field.getName()))
.collect(Collectors.joining(", "));

Assert.fail("Fields with functional types that are not serializable: "
+ nonSerializableString);
}

private void failSerializableClasses(
ArrayList<Class<?>> nonSerializableClasses) {
String nonSerializableString = "";
Iterator<Class<?>> it = nonSerializableClasses.iterator();
while (it.hasNext()) {
Class<?> c = it.next();
nonSerializableString += ", " + c.getName();
if (c.isAnonymousClass()) {
nonSerializableString += "(super: ";
nonSerializableString += c.getSuperclass().getName();
nonSerializableString += ", interfaces: ";
for (Class<?> i : c.getInterfaces()) {
nonSerializableString += i.getName();
nonSerializableString += ",";
} }
nonSerializableString += ")";
} }
Assert.fail(
"Serializable not implemented by the following classes and interfaces: "
+ nonSerializableString);
} }
Assert.fail(
"Serializable not implemented by the following classes and interfaces: "
+ nonSerializableString);
}

private static boolean isFunctionalType(Type type) {
return type.getTypeName().contains("java.util.function");
} }


private boolean isTestClass(Class<?> cls) { private boolean isTestClass(Class<?> cls) {
* *
* @return List of class path segment strings * @return List of class path segment strings
*/ */
//
private final static List<String> getRawClasspathEntries() { private final static List<String> getRawClasspathEntries() {
// try to keep the order of the classpath // try to keep the order of the classpath
List<String> locations = new ArrayList<>(); List<String> locations = new ArrayList<>();

+ 8
- 10
server/src/test/java/com/vaadin/tests/server/component/grid/GridDefaultHeaderTest.java View File

import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame; import static org.junit.Assert.assertSame;


import java.util.function.Function;

import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;


import com.vaadin.server.SerializableFunction;
import com.vaadin.ui.Grid; import com.vaadin.ui.Grid;
import com.vaadin.ui.Grid.Column; import com.vaadin.ui.Grid.Column;
import com.vaadin.ui.Grid.HeaderRow; import com.vaadin.ui.Grid.HeaderRow;
public void setUp() { public void setUp() {
grid = new Grid<>(); grid = new Grid<>();


column1 = grid.addColumn("First", Function.identity());
column2 = grid.addColumn("Second", Function.identity());
column1 = grid.addColumn("First", SerializableFunction.identity());
column2 = grid.addColumn("Second", SerializableFunction.identity());
} }


@Test @Test
public void initialState_updateColumnCaption_defaultHeaderUpdated() { public void initialState_updateColumnCaption_defaultHeaderUpdated() {
column1.setCaption("1st"); column1.setCaption("1st");


assertEquals("1st", grid.getDefaultHeaderRow().getCell(column1)
.getText());
assertEquals("1st",
grid.getDefaultHeaderRow().getCell(column1).getText());
} }


@Test @Test
grid.setDefaultHeaderRow(grid.appendHeaderRow()); grid.setDefaultHeaderRow(grid.appendHeaderRow());
column1.setCaption("1st"); column1.setCaption("1st");


assertEquals("1st", grid.getDefaultHeaderRow().getCell(column1)
.getText());
assertEquals("1st",
grid.getDefaultHeaderRow().getCell(column1).getText());
assertEquals("First", grid.getHeaderRow(0).getCell(column1).getText()); assertEquals("First", grid.getHeaderRow(0).getCell(column1).getText());
} }


grid.setDefaultHeaderRow(null); grid.setDefaultHeaderRow(null);
column1.setCaption("1st"); column1.setCaption("1st");


assertEquals("First", grid.getHeaderRow(0).getCell(column1)
.getText());
assertEquals("First", grid.getHeaderRow(0).getCell(column1).getText());
} }
} }

+ 5
- 4
server/src/test/java/com/vaadin/tests/server/component/grid/GridHeaderFooterTest.java View File

import static org.junit.Assert.assertSame; import static org.junit.Assert.assertSame;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;


import java.util.function.Function;

import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;


import com.vaadin.server.SerializableFunction;
import com.vaadin.ui.Grid; import com.vaadin.ui.Grid;
import com.vaadin.ui.Grid.Column; import com.vaadin.ui.Grid.Column;
import com.vaadin.ui.Grid.HeaderRow; import com.vaadin.ui.Grid.HeaderRow;


@Test @Test
public void addColumn_headerCellAdded() { public void addColumn_headerCellAdded() {
Column<?, ?> column = grid.addColumn("Col", Function.identity());
Column<?, ?> column = grid.addColumn("Col",
SerializableFunction.identity());


assertNotNull(grid.getHeaderRow(0).getCell(column)); assertNotNull(grid.getHeaderRow(0).getCell(column));
} }


@Test(expected = IllegalArgumentException.class) @Test(expected = IllegalArgumentException.class)
public void removeColumn_headerCellRemoved() { public void removeColumn_headerCellRemoved() {
Column<String, ?> column = grid.addColumn("Col", Function.identity());
Column<String, ?> column = grid.addColumn("Col",
SerializableFunction.identity());
grid.removeColumn(column); grid.removeColumn(column);


grid.getHeaderRow(0).getCell(column); grid.getHeaderRow(0).getCell(column);

+ 3
- 4
server/src/test/java/com/vaadin/tests/server/component/grid/GridTest.java View File



import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;


import java.util.function.Function;

import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;


import com.vaadin.server.SerializableFunction;
import com.vaadin.shared.ui.grid.HeightMode; import com.vaadin.shared.ui.grid.HeightMode;
import com.vaadin.ui.Grid; import com.vaadin.ui.Grid;
import com.vaadin.ui.renderers.NumberRenderer; import com.vaadin.ui.renderers.NumberRenderer;
@Before @Before
public void setUp() { public void setUp() {
grid = new Grid<>(); grid = new Grid<>();
grid.addColumn("foo", Function.identity());
grid.addColumn("foo", SerializableFunction.identity());
grid.addColumn(String::length, new NumberRenderer()); grid.addColumn(String::length, new NumberRenderer());
grid.addColumn("randomColumnId", Function.identity());
grid.addColumn("randomColumnId", SerializableFunction.identity());
} }


@Test @Test

+ 2
- 2
uitest/src/main/java/com/vaadin/tests/components/grid/GridApplyFilterWhenScrolledDown.java View File



import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.function.Function;


import com.vaadin.server.SerializableFunction;
import com.vaadin.server.VaadinRequest; import com.vaadin.server.VaadinRequest;
import com.vaadin.server.data.DataSource; import com.vaadin.server.data.DataSource;
import com.vaadin.tests.components.AbstractTestUI; import com.vaadin.tests.components.AbstractTestUI;
protected void setup(VaadinRequest request) { protected void setup(VaadinRequest request) {
Grid<String> grid = new Grid<>(); Grid<String> grid = new Grid<>();


grid.addColumn("Name", Function.identity());
grid.addColumn("Name", SerializableFunction.identity());


List<String> data = new ArrayList<>(); List<String> data = new ArrayList<>();
for (int i = 0; i < 1000; i++) { for (int i = 0; i < 1000; i++) {

Loading…
Cancel
Save