CORDA-908 - Support private properties in AMQP serialization (#2336)

CORDA-908 - Support private properties in AMQP serialization

* Review comments

* Fix tests

* Review Comments

* review comments

* review comments
This commit is contained in:
Katelyn Baker
2018-01-10 11:41:49 +00:00
committed by GitHub
parent 979d7f2c63
commit cacdba872e
14 changed files with 430 additions and 84 deletions

View File

@ -16,19 +16,31 @@ Unreleased
That is the ability to alter an enum constant and, as long as certain rules are followed and the correct
annotations applied, have older and newer instances of that enumeration be understood.
* **AMQP Enabled**
* **AMQP Enabled**:
AMQP Serialization is now enabled for both peer to peer communication and the writing of states to the vault. This change
brings a stable format Corda can support internally throughout it's lifetime that meets the needs of Corda and our
users.
AMQP Serialization is now enabled for both peer to peer communication and writing states to the vault. This change
brings a stable format Corda can support internally throughout it's lifetime that meets the needs of Corda and our
users.
Details on the AMQP serialization framework can be found in the :doc:`serialization` document :ref:`here <amqp_ref>`.
This provides an introduction and overview of the framework whilst more specific details on object evolution as it relates to
serialization is similarly found in pages :doc:`serialization-default-evolution` and :doc:`serialization-enum-evolution`
respectively. Recommendations on how best to code CorDapps using your own :ref:`custom types <amqp_custom_types_ref>`.
.. note:: This release delivers the bulk of our transition from Kryo serialisation to AMQP serialisation. This means that many of the restrictions
that were documented in previous versions of Corda are now enforced. (https://docs.corda.net/releases/release-V1.0/serialization.html).
In particular, you are advised to review the section titled "Custom Types". To aid with the transition, we have included support
in this release for default construction of objects and their instantiation through getters as well as objects with inaccessible
private fields but it is not guaranteed that this support will continue into future versions; the restrictions documented at the
link above are the canonical source.
* **Custom Serializers**
To allow interop with third party libraries that cannot be recompiled we add functionality that allows custom serializers
to be written for those classes. If needed, a proxy object can be created as an interim step that allows Corda's internal
serializers to operate on those types.
To allow interop with third party libraries that cannot be recompiled we add functionality that allows custom serializers
to be written for those classes. If needed, a proxy object can be created as an interim step that allows Corda's internal
serializers to operate on those types.
A good example of this is the SIMM valuation demo which has a number of such serializers defined in the plugin/customserializers package
A good example of this is the SIMM valuation demo which has a number of such serializers defined in the plugin/customserializers package
Release 2.0
----------

View File

@ -1,6 +1,8 @@
Object serialization
====================
.. contents::
What is serialization (and deserialization)?
--------------------------------------------
@ -52,7 +54,7 @@ was a compelling use case for the definition and development of a custom format
#. A desire to have a schema describing what has been serialized along-side the actual data:
#. To assist with versioning, both in terms of being able to interpret long ago archivEd data (e.g. trades from
#. To assist with versioning, both in terms of being able to interpret long ago archived data (e.g. trades from
a decade ago, long after the code has changed) and between differing code versions.
#. To make it easier to write user interfaces that can navigate the serialized form of data.
#. To support cross platform (non-JVM) interaction, where the format of a class file is not so easily interpreted.
@ -76,7 +78,7 @@ Finally, for the checkpointing of flows Corda will continue to use the existing
This separation of serialization schemes into different contexts allows us to use the most suitable framework for that context rather than
attempting to force a one size fits all approach. Where ``Kryo`` is more suited to the serialization of a programs stack frames, being more flexible
than our AMQP framework in what it can construct and serialize, that flexibility makes it exceptionally difficult to make secure. Conversly
than our AMQP framework in what it can construct and serialize, that flexibility makes it exceptionally difficult to make secure. Conversely
our AMQP framework allows us to concentrate on a robust a secure framework that can be reasoned about thus made safer with far fewer unforeseen
security holes.
@ -282,22 +284,6 @@ serialised form
val e2 = e.serialize().deserialize() // e2.c will be 20, not 100!!!
.. warning:: Private properties in Kotlin classes render the class unserializable *unless* a public
getter is manually defined. For example:
.. container:: codeset
.. sourcecode:: kotlin
data class C(val a: Int, private val b: Int) {
// Without this C cannot be serialized
public fun getB() = b
}
.. note:: This is particularly relevant as IDE's can often point out where they believe a
property can be made private without knowing this can break Corda serialization. Should
this happen then a run time warning will be generated when the class fails to serialize
Setter Instantiation
''''''''''''''''''''
@ -330,6 +316,75 @@ For example:
public void setC(int c) { this.c = c; }
}
Inaccessible Private Properties
```````````````````````````````
Whilst the Corda AMQP serialization framework supports private object properties without publicly
accessible getter methods this development idiom is strongly discouraged.
For example.
.. container:: codeset
Kotlin:
.. sourcecode:: kotlin
data class C(val a: Int, private val b: Int)
Java:
.. sourcecode:: Java
class C {
public Integer a;
private Integer b;
C(Integer a, Integer b) {
this.a = a;
this.b = b;
}
}
When designing stateful objects is should be remembered that they are not, despite appearances, traditional
programmatic constructs. They are signed over, transformed, serialised, and relationally mapped. As such,
all elements should be publicly accessible by design
.. warning:: IDEs will indiciate erroneously that properties can be given something other than public
visibility. Ignore this as whilst it will work, as discussed above there are many reasons why this isn't
a good idea and those are beyond the scope of the IDEs inference rules
Providing a public getter, as per the following example, is acceptable
.. container:: codeset
Kotlin:
.. sourcecode:: kotlin
data class C(val a: Int, private val b: Int) {
public fun getB() = b
}
Java:
.. sourcecode:: Java
class C {
public Integer a;
private Integer b;
C(Integer a, Integer b) {
this.a = a;
this.b = b;
}
public Integer getB() {
return b;
}
}
Enums
`````