In the backend, after we have created an offer in our Cosmo system, I’d like to save the cosmo offer id in my a12 document.
So, in Java code: What is a simple way to set a field value?
I came up with
((FieldInstance) queryFactory.createPathQuery(COSMO_OFFER_ID_PATH, document.getDocumentRoot()).findSingle()).setValue(cosmoOfferId);
(plus error/exception handling)
However, that fails because there is no FieldInstance ever created for the field. It seems field instances actually only get created by the form engine - but of course, this field is not part of the ui.
Is there a way to create all necessary groups/elements along a given path into the document model?
If the field’s parent already exists, I came up with this, but srsly that should be easier and more generic.
private void createStringField(Document document, String path, String value) {
int lastIndexOfSlash = path.lastIndexOf('/');
if (lastIndexOfSlash == -1) {
throw new FaultException("Cannot set field value " + path);
}
String parentPath = path.substring(0, lastIndexOfSlash);
String elementName = path.substring(lastIndexOfSlash + 1);
GroupInstance parent = (GroupInstance) findSingleElement(parentPath, document);
Group group = parent.getModelElement();
Field element = (Field) group.getElements()
.stream()
.filter(el -> elementName.equals(el.getName()))
.findFirst()
.orElseThrow(() -> new FaultException("Element not found " + path));
StringFieldInstance fieldInstance = new StringFieldInstance(element, parent, Optional.of(value));
parent.getChildren().add(fieldInstance);
}
Any updates on this? Is there now a more straightforward way to either set a value on a FieldInstance if it already exists or implicitly create it with the desired value?
Moin @marcel-calm-dew,
currently the solution for 2023.06-ext6 could be implemented as follows for a specific field with given path:
@Component
public class TestEventListener {
@Autowired
IDocumentFactory documentFactory;
@EventListener
public void settingAFieldInstance(DocumentBeforeCreateEvent event) {
IDocument document = event.getCreatedDocument();
// Create the new FieldInstance with a value
IFieldInstance placeOfBirthInstance = documentFactory.createFieldInstance("/Person/PersonalData/PlaceOfBirth", new int[]{1,1,1});
placeOfBirthInstance.setValue("Nuremberg");
// If present, removes the FieldInstance
document.removeEntityInstance(placeOfBirthInstance);
// Adds the FieldInstance
document.addEntityInstance(placeOfBirthInstance);
}
}
As an outlook for 2024.06
Access to documents and the modification of fields will be simplified with a new DocumentV2 API from Kernel. This will not yet replace the old API but it will make it easier to read and update documents.
E.g. the Search, remove and adding from the code snippet above could look like this for a given document (including the conversion of an IDocument of DocumentV1 API to DocumentV2):
DocumentV2 documentV2 = documentV1V2Convertor.ofDocumentV1(documentV1);
documentV2 = documentV2.withFieldValue("/Person[1]/PersonalData[1]/PlaceOfBirth", "Nuremberg");
I hope this answers your question, otherwise feel free to ask for more details 
Hi Jan, thanks for this update and outlook on the new API!
Thanks for the answer! A follow-up question for the new way in 2024.06:
How am I supposed to get hold of documentV1V2Convertor?
There is no pre-configured Spring bean (as there is for many other a12 classes like IDocumentRepository) and the class DocumentV1V2ConverterImpl that implements the IDocumentV1V2Converter interface is in an internal package.
I can suppress the Checkstyle warning in my setup and depend on an a12 internal package, but I suppose that’s not the intended usage, or is it?
Moin @stephen-warm-graph,
you can get an instance of IDocumentV1V2Converter via using the DocumentServiceFactory#createDocumentV1V2Converter.
The DocumentServiceFactory can be just autowired, because Data Services offers autoconfiguration for this bean.
Usage of the DocumentV2 API and way more in detail explanations can be found in the Kernel DocumentV2 API documentation.