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

Make classes serializable #4148

Merged
merged 18 commits into from
May 24, 2018
Merged

Make classes serializable #4148

merged 18 commits into from
May 24, 2018

Conversation

elmot
Copy link
Contributor

@elmot elmot commented May 21, 2018

Partial fix for vaadin/platform#173
Related to #4105


This change is Reviewable


/**
* An event fired when the value of a {@code HasValue} changes.
*
* @param <V>
* the value type
*/
interface ValueChangeEvent<V> {
interface ValueChangeEvent<V> extends Serializable {
HasValue<?, V> getHasValue();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MAJOR Remove usage of generic wildcard type. rule

@caalador
Copy link
Contributor

JavaDoc fails build.

@denis-anisimov
Copy link
Contributor

Reviewed 47 of 54 files at r1, 9 of 10 files at r2.
Review status: all files reviewed at latest revision, 15 unresolved discussions, some commit checks failed.


flow-server/src/main/java/com/vaadin/flow/dom/ElementFactory.java, line 28 at r2 (raw file):

ElementFactory 

This is a mix-in without any single instance method.
Technically it's just a util class. So doesn't have to be serializable.
But it doesn't hurt.


flow-server/src/main/java/com/vaadin/flow/dom/NodeVisitor.java, line 28 at r2 (raw file):

 extends Serializable 

That may be wrong......
I'm not sure.
Visitor is not intended to be stored in any state. It's temporary logic which is applied during request handling. So it's too much to require it to be serializable.


flow-server/src/main/java/com/vaadin/flow/dom/impl/ThemeListImpl.java, line 18 at r2 (raw file):

import java.io.Serializable;

No other changes in this class.
Is it a mistake or something is missed ?


flow-server/src/main/java/com/vaadin/flow/router/RouteNotFoundError.java, line 118 at r2 (raw file):

        private LazyInit() {
        }

Why ?
The class is inner private.
What's the benefit to have explicit CTOR here ?


flow-server/src/main/java/com/vaadin/flow/templatemodel/PropertyMapBuilder.java, line 131 at r2 (raw file):

SerializablePredicate<String>

This is not really needed.
This predicate is not stored anywhere. It's used only at the creation time to filter the data and then it's lost.
But it looks this filter is our own filter which we may force to be serializable.


flow-server/src/main/java/com/vaadin/flow/templatemodel/TemplateModel.java, line 188 at r2 (raw file):

SerializablePredicate<String>

I would say this is a mistake here to require Serializable.
Looks like this filter is used only to filter the data during other data creation and then it's not stored anywhere.
So it's too restrictive to require serializable here.


Comments from Reviewable

@elmot
Copy link
Contributor Author

elmot commented May 22, 2018

Review status: 47 of 53 files reviewed at latest revision, 19 unresolved discussions.


flow-server/src/main/java/com/vaadin/flow/dom/ElementFactory.java, line 28 at r2 (raw file):

Previously, denis-anisimov (Denis) wrote…
ElementFactory 

This is a mix-in without any single instance method.
Technically it's just a util class. So doesn't have to be serializable.
But it doesn't hurt.

Done.


flow-server/src/main/java/com/vaadin/flow/dom/NodeVisitor.java, line 28 at r2 (raw file):

Previously, denis-anisimov (Denis) wrote…
 extends Serializable 

That may be wrong......
I'm not sure.
Visitor is not intended to be stored in any state. It's temporary logic which is applied during request handling. So it's too much to require it to be serializable.

Done.


flow-server/src/main/java/com/vaadin/flow/router/RouteNotFoundError.java, line 118 at r2 (raw file):

Previously, denis-anisimov (Denis) wrote…
        private LazyInit() {
        }

Why ?
The class is inner private.
What's the benefit to have explicit CTOR here ?

Technically there is no need of the CTOR, it's added to make code self-documented.


flow-server/src/main/java/com/vaadin/flow/templatemodel/TemplateModel.java, line 188 at r2 (raw file):

Previously, denis-anisimov (Denis) wrote…
SerializablePredicate<String>

I would say this is a mistake here to require Serializable.
Looks like this filter is used only to filter the data during other data creation and then it's not stored anywhere.
So it's too restrictive to require serializable here.

Are PropertyFilters stored anywhere? If yes, then it should be made of SerializablePredicates and all classes around should be serializable as well. If not, then they could be reverted back to non-serializable version


Comments from Reviewable

@denis-anisimov
Copy link
Contributor

Reviewed 3 of 9 files at r3.
Review status: 50 of 53 files reviewed at latest revision, 18 unresolved discussions, some commit checks failed.


flow-server/src/main/java/com/vaadin/flow/router/RouteNotFoundError.java, line 118 at r2 (raw file):

Previously, elmot (Ilia Motornyi) wrote…

Technically there is no need of the CTOR, it's added to make code self-documented.

Don't see how it makes self-documented code for the class which is nested and not visible from anywhere. Extra CTOR just adds more lines and what's bad: this change has no any relation to the main purpose of the PR.

But it's minor.


flow-server/src/main/java/com/vaadin/flow/templatemodel/TemplateModel.java, line 188 at r2 (raw file):

Previously, elmot (Ilia Motornyi) wrote…

Are PropertyFilters stored anywhere? If yes, then it should be made of SerializablePredicates and all classes around should be serializable as well. If not, then they could be reverted back to non-serializable version

That's the question.
The filter is stored inside an instance of PropertyFilter. But the PropertyFilter instance is not stored anywhere. It's temporary instance.
I didn't find any code which stores this instance.
And if PropertyFilter also requires serializable filter in its CTOR it also should be reverted.


Comments from Reviewable

@denis-anisimov
Copy link
Contributor

Reviewed 6 of 9 files at r3.
Review status: all files reviewed at latest revision, 17 unresolved discussions, some commit checks failed.


flow-server/src/test/java/com/vaadin/tests/server/ClassesSerializableTest.java, line 213 at r3 (raw file):

test

useless prefix. But it's minor.


Comments from Reviewable

@elmot
Copy link
Contributor Author

elmot commented May 22, 2018

Review status: all files reviewed at latest revision, 17 unresolved discussions, some commit checks failed.


flow-server/src/main/java/com/vaadin/flow/templatemodel/TemplateModel.java, line 188 at r2 (raw file):

Previously, denis-anisimov (Denis) wrote…

That's the question.
The filter is stored inside an instance of PropertyFilter. But the PropertyFilter instance is not stored anywhere. It's temporary instance.
I didn't find any code which stores this instance.
And if PropertyFilter also requires serializable filter in its CTOR it also should be reverted.

Ok, I am reverting both.


flow-server/src/main/java/com/vaadin/flow/component/internal/ComponentMetaData.java, line 58 at r1 (raw file):

Previously, vaadin-bot (Vaadin Bot) wrote…

MAJOR Make "javaScripts" transient or serializable. rule

Done.


flow-server/src/main/java/com/vaadin/flow/component/internal/ComponentMetaData.java, line 59 at r1 (raw file):

Previously, vaadin-bot (Vaadin Bot) wrote…

MAJOR Make "styleSheets" transient or serializable. rule

Done.


Comments from Reviewable

@denis-anisimov
Copy link
Contributor

Review status: all files reviewed at latest revision, 17 unresolved discussions, some commit checks failed.


flow-server/src/main/java/com/vaadin/flow/templatemodel/TemplateModel.java, line 188 at r2 (raw file):

Previously, elmot (Ilia Motornyi) wrote…

Ok, I am reverting both.

No changes.
Not committed ?


Comments from Reviewable

@denis-anisimov
Copy link
Contributor

Reviewed 4 of 7 files at r4.
Review status: all files reviewed at latest revision, 10 unresolved discussions, some commit checks broke.


Comments from Reviewable

@elmot
Copy link
Contributor Author

elmot commented May 23, 2018

Review status: all files reviewed at latest revision, 9 unresolved discussions, some commit checks broke.


flow-server/src/main/java/com/vaadin/flow/component/polymertemplate/TemplateDataAnalyzer.java, line 107 at r1 (raw file):

        private final Map<String, String> tagById;
        private final Map<Field, String> idByField;

Done.


Comments from Reviewable

@elmot
Copy link
Contributor Author

elmot commented May 23, 2018

Review status: 42 of 48 files reviewed at latest revision, 5 unresolved discussions.


flow-server/src/main/java/com/vaadin/flow/dom/impl/ThemeListImpl.java, line 18 at r2 (raw file):

Previously, denis-anisimov (Denis) wrote…
import java.io.Serializable;

No other changes in this class.
Is it a mistake or something is missed ?

Done. Now there are changes


flow-server/src/main/java/com/vaadin/flow/router/RouteNotFoundError.java, line 118 at r2 (raw file):

Previously, denis-anisimov (Denis) wrote…

Don't see how it makes self-documented code for the class which is nested and not visible from anywhere. Extra CTOR just adds more lines and what's bad: this change has no any relation to the main purpose of the PR.

But it's minor.

Done.


flow-server/src/main/java/com/vaadin/flow/templatemodel/PropertyMapBuilder.java, line 131 at r2 (raw file):

Previously, denis-anisimov (Denis) wrote…
SerializablePredicate<String>

This is not really needed.
This predicate is not stored anywhere. It's used only at the creation time to filter the data and then it's lost.
But it looks this filter is our own filter which we may force to be serializable.

Done.


Comments from Reviewable

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

List<Class<?>> nonSerializableClasses = new ArrayList<>();
for (String className : classes) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MAJOR Reduce the total number of break and continue statements in this loop to use at most one. rule

@denis-anisimov
Copy link
Contributor

Reviewed 1 of 8 files at r4, 1 of 3 files at r5, 7 of 10 files at r6.
Review status: all files reviewed at latest revision, 27 unresolved discussions, some commit checks broke.


flow-test-generic/pom.xml, line 22 at r6 (raw file):

</project>

new line


Comments from Reviewable

@elmot
Copy link
Contributor Author

elmot commented May 23, 2018

Review status: 47 of 49 files reviewed at latest revision, 28 unresolved discussions.


flow-test-generic/pom.xml, line 22 at r6 (raw file):

Previously, denis-anisimov (Denis) wrote…

new line

Done.


flow-test-generic/src/main/java/com/vaadin/flow/testutil/ClassesSerializableTest.java, line 36 at r6 (raw file):

Previously, vaadin-bot (Vaadin Bot) wrote…

CRITICAL Document this public class by adding an explicit description. rule

Done.


flow-test-generic/src/main/java/com/vaadin/flow/testutil/ClassesSerializableTest.java, line 117 at r6 (raw file):

Previously, vaadin-bot (Vaadin Bot) wrote…

MINOR Remove this empty statement. rule

Done.


flow-test-generic/src/main/java/com/vaadin/flow/testutil/ClassesSerializableTest.java, line 119 at r6 (raw file):

Previously, vaadin-bot (Vaadin Bot) wrote…

CRITICAL Document this public method by adding an explicit description. rule
MAJOR Refactor this method to throw at most one checked exception instead of: java.io.IOException, java.lang.ClassNotFoundException rule

Done.


Comments from Reviewable

@denis-anisimov
Copy link
Contributor

Reviewed 2 of 3 files at r7.
Review status: all files reviewed at latest revision, 27 unresolved discussions.


Comments from Reviewable

} else if (getJarPattern().matcher(file.getName()).matches()) {
classes = findClassesInJar(file);
} else {
logger.debug("Ignoring " + classpathEntry);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MAJOR Use the built-in formatting to construct this argument. rule

@denis-anisimov
Copy link
Contributor

Reviewed 1 of 2 files at r9.
Review status: all files reviewed at latest revision, all discussions resolved.


flow-test-generic/src/main/java/com/vaadin/flow/testutil/ClassesSerializableTest.java, line 315 at r9 (raw file):

if (iface == Runnable.class || iface == Comparator.class) {

So if I implement a Runnable or Comparator class myself which is a real class it will be skipped?

I think it should check something isAnonymousClass() or isSynthetic() or whatever.

And isSkippable is a bad name. It should say why it may be ignored (or just canIgnore ).


Comments from Reviewable

@elmot
Copy link
Contributor Author

elmot commented May 24, 2018

Review status: 48 of 49 files reviewed at latest revision, 1 unresolved discussion.


flow-test-generic/src/main/java/com/vaadin/flow/testutil/ClassesSerializableTest.java, line 315 at r9 (raw file):

Previously, denis-anisimov (Denis) wrote…
if (iface == Runnable.class || iface == Comparator.class) {

So if I implement a Runnable or Comparator class myself which is a real class it will be skipped?

I think it should check something isAnonymousClass() or isSynthetic() or whatever.

And isSkippable is a bad name. It should say why it may be ignored (or just canIgnore ).

I also had some concerns about this code. Removed.


Comments from Reviewable

* @throws Throwable serialization goes wrong
*/
@Test
public void classesSerializable() throws Throwable {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MAJOR Define and throw a dedicated exception instead of using a generic one. rule

// report non-serializable classes and interfaces
if (!Serializable.class.isAssignableFrom(cls)) {
nonSerializableClasses.add(cls);
// TODO easier to read when testing
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

INFO Complete the task associated to this TODO comment. rule

if (!Serializable.class.isAssignableFrom(cls)) {
nonSerializableClasses.add(cls);
// TODO easier to read when testing
// System.err.println(cls);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MAJOR This block of commented-out lines of code should be removed. rule

@elmot
Copy link
Contributor Author

elmot commented May 24, 2018

Review status: 48 of 49 files reviewed at latest revision, 2 unresolved discussions.


flow-test-generic/src/main/java/com/vaadin/flow/testutil/ClassesSerializableTest.java, line 148 at r10 (raw file):

serializeAndDeserialize

Comments from Reviewable

*/
@SuppressWarnings({"UnusedReturnValue", "WeakerAccess"})
public <T> T serializeAndDeserialize(T instance)
throws Throwable {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MAJOR Define and throw a dedicated exception instead of using a generic one. rule

@vaadin-bot
Copy link
Collaborator

SonarQube analysis reported 16 issues

  • MAJOR 13 major
  • MINOR 2 minor
  • INFO 1 info

Watch the comments in this conversation to review them.

9 extra issues

Note: The following issues were found on lines that were not modified in the pull request. Because these issues can't be reported as line comments, they are summarized here:

  1. MAJOR EventDataCache.java#L1: Class com.vaadin.flow.component.internal.EventDataCache defines non-transient non-serializable instance field eventConstructors rule
  2. MAJOR ElementListenerMap.java#L368: Rename "listeners" which hides the field declared at line 58. rule
  3. MAJOR InitialPageSettings.java#L1: Class com.vaadin.flow.server.InitialPageSettings defines non-transient non-serializable instance field elements rule
  4. MAJOR InitialPageSettings.java#L1: Class com.vaadin.flow.server.InitialPageSettings defines non-transient non-serializable instance field request rule
  5. MAJOR InitialPageSettings.java#L55: Make "request" transient or serializable. rule
  6. MAJOR InitialPageSettings.java#L65: Make "elements" transient or serializable. rule
  7. MAJOR RouteRegistry.java#L575: A "NullPointerException" could be thrown; "navigationTarget" is nullable here. rule
  8. MINOR ReflectionCache.java#L82: Remove this unnecessary cast to "Function". rule
  9. MINOR ElementListenerMap.java#L327: Move this method into "DomEventListenerWrapper". rule

@denis-anisimov
Copy link
Contributor

:lgtm:


Reviewed 1 of 2 files at r11.
Review status: all files reviewed at latest revision, all discussions resolved.


Comments from Reviewable

@denis-anisimov denis-anisimov merged commit bad717d into master May 24, 2018
@denis-anisimov denis-anisimov deleted the serialization branch May 24, 2018 08:59
@pekam pekam added this to the 1.0.0.beta12 milestone May 24, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants