In both of the cases, a developer can set/update the binary Property
via Node.setProperty(String, InputStream)
, Property.setValue(InputStream)
as described in the JSR-170 specification. Also, there is the setter with a ready
Value object (obtaining from ValueFactory.createValue(InputStream)
).
An example of a specification usage.
// Set the property value with given stream content.
Property binProp = node.setProperty("BinData", myDataStream);
// Get the property value stream.
InputStream binStream = binProp.getStream();
// You may change the binary property value with a new Stream, all data will be replaced
// with the content from the new stream.
Property updatedBinProp = node.setProperty("BinData", newDataStream);
// Or update an obtained property
updatedBinProp.setValue(newDataStream);
// Or update using a Value object
updatedBinProp.setValue(ValueFactory.createValue(newDataStream));
// Get the updated property value stream.
InputStream newStream = updatedBinProp.getStream();
But if you need to update the property sequentially and with partial content, you have no choice but to edit the whole data stream outside and get it back to the repository each time. In case of really large-sized data, the application will be stuck and the productivity will decrease a lot. JCR stream setters will also check constraints and perform common validation each time.
There is a feature of the eXo JCR extension that can be used for binary values partial writing without frequent session level calls. The main idea is to use a value object obtained from the property as the storage of the property content while writing/reading during runtime.
According to the JSR-170 specification, Value interface
provides the state of
property that cannot be changed (edited). The eXo JCR core provides the
ReadableBinaryValue
and EditableBinaryValue
interfaces which themselves
extend the JCR value. The interfaces allow the user to partially read and
change a value content.
The ReadableBinaryValue
value can be casted from any values, such as String,
Binary, Date, and more.
// get the property value of type PropertyType.STRING
ReadableBinaryValue extValue = (ReadableBinaryValue) node.getProperty("LargeText").getValue();
// read 200 bytes to a destStream from the position 1024 in the value content
OutputStream destStream = new FileOutputStream("MyTextFile.txt");
extValue.read(destStream, 200, 1024);
But
EditableBinaryValue
can be applied only to properties of the
PropertyType.BINARY
type. In other cases, a cast to EditableBinaryValue will
fail.
After the value has been edited, the EditableBinaryValue value can
be applied to the property using the standard setters
(for example, Property.setValue(Value)
, Property.setValues(Value)
,
Node.setProperty(String, Value)
). Only after the EditableBinaryValue
has been set to the property, it can be obtained in this session by
getters (for example, Property.getValue()
, Node.getProperty(String)
).
The user can obtain an EditableBinaryValue
instance and fill it with
data in an interaction manner (or any other appropriated to the targets)
and return (set) the value to the property after the content is
done.
// get the property value for PropertyType.BINARY Property
EditableBinaryValue extValue = (EditableBinaryValue) node.getProperty("BinData").getValue();
// update length bytes from the stream starting from the position 1024 in existing Value data
extValue.update(dataInputStream, dataLength, 1024);
// apply the edited EditableBinaryValue to the Property
node.setProperty("BinData", extValue);
// save the Property to persistence
node.save();
See a practical example of the iterative usage. In this example, the value is updated with data from the sequence of streams and after the update is done, the value will be applied to the property and be visible during the session.
// update length bytes from the stream starting from the particular
// position in the existing Value data
int dpos = 1024;
while (source.dataAvailable()) {
extValue.update(source.getInputStream(), source.getLength(), dpos);
dpos = dpos + source.getLength();
}
// apply the edited EditableBinaryValue to the Property
node.setProperty("BinData", extValue);