Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Grid without columns failed to serialize #14654

Closed
davidef opened this issue Sep 27, 2022 · 6 comments · Fixed by #14870
Closed

Grid without columns failed to serialize #14654

davidef opened this issue Sep 27, 2022 · 6 comments · Fixed by #14870

Comments

@davidef
Copy link

davidef commented Sep 27, 2022

Description of the bug

Grid without columns failed to serialize with the following exception:
cannot assign instance of java.lang.invoke.SerializedLambda to field com.vaadin.flow.data.provider.AbstractDataProvider$DataListenerWrapper.registration of type com.vaadin.flow.shared.Registration in instance of com.vaadin.flow.data.provider.AbstractDataProvider$DataListenerWrapper
In own production code the same exception happens also with columns configured but we weren't able to create a minimal reproducible example.

Minimal reproducible example

@Route(value = "grid-serialization")
public class GridSerializationIssue extends VerticalLayout {
	private static final long serialVersionUID = 1L;
	
	private final Grid<Currency> grid;

	public GridSerializationIssue() {
		Button test = new Button("serialize", event -> {
			try {
				ByteArrayOutputStream bos = new ByteArrayOutputStream();
				try(ObjectOutputStream oos = new ObjectOutputStream(bos)){
					oos.writeObject(GridSerializationIssue.this);
					oos.flush();
				}
				try(ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray())){
					try(ObjectInputStream ois = new ObjectInputStream(bis)){
						GridSerializationIssue readObject = (GridSerializationIssue) ois.readObject();
					}
				}
				Notification.show("OK");
			}catch (Exception e) {
				e.printStackTrace();
				Notification.show("FAILED: " + e.getMessage());
			}
		});
		add(test);

		grid = new Grid<>();
		add(grid);
	}
	
	public static class Currency implements Serializable{
		private static final long serialVersionUID = 1L;
		
		private String code;
		private String currency;
		private String symbol;
		
		public Currency(){}

		public String getCurrency() {
			return currency;
		}

		public void setCurrency(String currency) {
			this.currency = currency;
		}
		
		public String getCode() {
			return code;
		}

		public void setCode(String code) {
			this.code = code;
		}

		public String getSymbol() {
			return symbol;
		}

		public void setSymbol(String symbol) {
			this.symbol = symbol;
		}
	}
}

Expected behavior

No exception throwed on serialization

Versions:

- Vaadin / Flow version: 23.2.2
- Java version: 17
- OS version: osx/linux
- Browser version (if applicable): -
- Application Server (if applicable): both tomcat and springboot
- IDE (if applicable): -
@davidef
Copy link
Author

davidef commented Sep 27, 2022

We managed to reproduce with a simple example also with the columns configured. We also find a even weird case were the first time it work and the second time it fails

Exception with also the columns configured.

@Route(value="grid-serialization-issue", layout = GridSerializationIssueWithColumnLayout.class)
public class GridSerializationIssueWithColumn extends VerticalLayout implements HasUrlParameter<String>{
	private static final long serialVersionUID = 1L;
	private Grid<Country> grid;

	public GridSerializationIssueWithColumn() {
		setHeightFull();

		grid = new Grid<>();
		grid.setSizeFull();

		grid.addColumn(Country::getCountrycode).setHeader("ISO Code").setWidth("100px").setFlexGrow(0);
		grid.addColumn(Country::getCountry).setHeader("Name").setFlexGrow(1);

		grid.setSelectionMode(SelectionMode.NONE);

		add(grid);
	}

	public void onFilterChange(String filter) {
		Country france = new Country();
		france.setCountry("France");
		france.setCountrycode("FR");

		grid.setItems(List.of(france));
	}

	@Override
	public void setParameter(BeforeEvent event, @OptionalParameter String parameter) {
		onFilterChange(parameter);
	}

	public static class GridSerializationIssueWithColumnLayout extends AppLayout {
		private static final long serialVersionUID = 1L;

		public GridSerializationIssueWithColumnLayout() {
			Button test = new Button("Serialize", event -> {
				try {
					ByteArrayOutputStream bos = new ByteArrayOutputStream();
					try(ObjectOutputStream oos = new ObjectOutputStream(bos)){
						oos.writeObject(GridSerializationIssueWithColumnLayout.this);
						oos.flush();
					}
					try(ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray())){
						try(ObjectInputStream ois = new ObjectInputStream(bis)){
							GridSerializationIssueWithColumnLayout readObject = (GridSerializationIssueWithColumnLayout) ois.readObject();
						}
					}
					Notification.show("OK");
				}catch (Exception e) {
					e.printStackTrace();
					Notification.show("FAILED: " + e.getMessage());
				}
			});
			
			addToNavbar(test);
		}
	}

	public static class Country implements Serializable {
		private static final long serialVersionUID = 1L;

		private String country;

		private String countrycode;

		public Country(){}

		public String getCountry() {
			return country;
		}

		public void setCountry(String country) {
			this.country = country;
		}

		public String getCountrycode() {
			return countrycode;
		}

		public void setCountrycode(String countrycode) {
			this.countrycode = countrycode;
		}
	}
}

The example below succeed the first time but fails the subsequents tries

@Route(value="grid-serialization-issue2")
public class GridSerializationIssue extends VerticalLayout implements HasUrlParameter<String>{
	private static final long serialVersionUID = 1L;
	private Grid<Country> grid;

	public GridSerializationIssue() {
		setHeightFull();
		
		Button test = new Button("Serialize", event -> {
			try {
				ByteArrayOutputStream bos = new ByteArrayOutputStream();
				try(ObjectOutputStream oos = new ObjectOutputStream(bos)){
					oos.writeObject(UI.getCurrent());
					oos.flush();
				}
				try(ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray())){
					try(ObjectInputStream ois = new ObjectInputStream(bis)){
						UI readObject = (UI) ois.readObject();
					}
				}
				Notification.show("OK");
			}catch (Exception e) {
				e.printStackTrace();
				Notification.show("FAILED: " + e.getMessage());
			}
		});
		
		add(test);

		grid = new Grid<>();
		grid.setSizeFull();

		grid.addColumn(Country::getCountrycode).setHeader("ISO Code").setWidth("100px").setFlexGrow(0);
		grid.addColumn(Country::getCountry).setHeader("Name").setFlexGrow(1);

		grid.setSelectionMode(SelectionMode.NONE);

		add(grid);
	}

	public void onFilterChange(String filter) {
		Country france = new Country();
		france.setCountry("France");
		france.setCountrycode("FR");

		grid.setItems(List.of(france));
	}

	@Override
	public void setParameter(BeforeEvent event, @OptionalParameter String parameter) {
		onFilterChange(parameter);
	}

	public static class Country implements Serializable {
		private static final long serialVersionUID = 1L;

		private String country;

		private String countrycode;

		public Country(){}

		public String getCountry() {
			return country;
		}

		public void setCountry(String country) {
			this.country = country;
		}

		public String getCountrycode() {
			return countrycode;
		}

		public void setCountrycode(String countrycode) {
			this.countrycode = countrycode;
		}
	}
}

@mshabarov
Copy link
Contributor

Looks similar to this issue #6216.

@mshabarov mshabarov moved this from Needs triage to P1 - High priority in OLD Vaadin Flow bugs & maintenance (Vaadin 10+) Oct 4, 2022
@mshabarov mshabarov moved this from Ready To Go to In progress in OLD Vaadin Flow ongoing work (Vaadin 10+) Oct 10, 2022
@caalador caalador moved this from P1 - High priority to WIP in OLD Vaadin Flow bugs & maintenance (Vaadin 10+) Oct 12, 2022
OLD Vaadin Flow ongoing work (Vaadin 10+) automation moved this from In progress to Done - pending release Oct 18, 2022
caalador pushed a commit that referenced this issue Oct 18, 2022
Replace lambda with anonymous inner class in AbstractDataProvider to fix serialization issue(s).
Test available in flow-components project since the issue only happens when the data provider is used with a grid.

Fixes #14654
OLD Vaadin Flow bugs & maintenance (Vaadin 10+) automation moved this from WIP to Closed Oct 18, 2022
vaadin-bot pushed a commit that referenced this issue Oct 18, 2022
Replace lambda with anonymous inner class in AbstractDataProvider to fix serialization issue(s).
Test available in flow-components project since the issue only happens when the data provider is used with a grid.

Fixes #14654
vaadin-bot pushed a commit that referenced this issue Oct 18, 2022
Replace lambda with anonymous inner class in AbstractDataProvider to fix serialization issue(s).
Test available in flow-components project since the issue only happens when the data provider is used with a grid.

Fixes #14654
vaadin-bot pushed a commit that referenced this issue Oct 18, 2022
Replace lambda with anonymous inner class in AbstractDataProvider to fix serialization issue(s).
Test available in flow-components project since the issue only happens when the data provider is used with a grid.

Fixes #14654
caalador pushed a commit that referenced this issue Oct 18, 2022
Replace lambda with anonymous inner class in AbstractDataProvider to fix serialization issue(s).
Test available in flow-components project since the issue only happens when the data provider is used with a grid.

Fixes #14654

Co-authored-by: Teppo Kurki <teppo.kurki@vaadin.com>
caalador pushed a commit that referenced this issue Oct 18, 2022
Replace lambda with anonymous inner class in AbstractDataProvider to fix serialization issue(s).
Test available in flow-components project since the issue only happens when the data provider is used with a grid.

Fixes #14654

Co-authored-by: Teppo Kurki <teppo.kurki@vaadin.com>
caalador pushed a commit that referenced this issue Oct 18, 2022
Replace lambda with anonymous inner class in AbstractDataProvider to fix serialization issue(s).
Test available in flow-components project since the issue only happens when the data provider is used with a grid.

Fixes #14654

Co-authored-by: Teppo Kurki <teppo.kurki@vaadin.com>
@vaadin-bot
Copy link
Collaborator

This ticket/PR has been released with Vaadin 23.1.13.

@davidef
Copy link
Author

davidef commented Oct 24, 2022

@caalador We just retested the examples above with vaadin 23.2.5 which should include the fix (according to https://github.com/vaadin/flow/commits/23.2.5 ) but they are still failing.
Also the issue was not present (for us) in vaadin 23.1.x

@caalador
Copy link
Contributor

Flow 23.2.5 will be in Vaadin 23.2.6 that should be available in mvn in a moment

@vaadin-bot
Copy link
Collaborator

This ticket/PR has been released with Vaadin 23.2.6.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment