minor
#29380
Kontextabhängige Auto-Nummerierung schlägt fehl, wenn Kontext und nummeriertes Objekt in einer Transaktion erzeugt werden
Beim Erzeugen eines Objekts mit einem kontextabhängigen Sequenz-Default (SequenceDefaultProvider bzw. NumberHandlerDefaultProvider mit <dynamic-sequence-name class="com.top_logic.element.structured.util.ContextAwareSequenceName"/>) schlägt die Nummernvergabe mit einer NullPointerException fehl, wenn der Kontext (das die Sequenz diskriminierende Objekt) und das nummerierte Objekt in derselben Transaktion angelegt werden.
Szenario
Ein Container (z.B. ein Projekt) und ein darin enthaltenes, auto-nummeriertes Element (z.B. ein Ticket mit projekt-lokaler laufender Nummer) werden in einem einzigen Commit erzeugt — beobachtet über den Instanz-Editor, der Container und Kind in einem Schritt anlegt; allgemeiner tritt es auf, sobald das Kontextobjekt beim Speichern noch nicht persistiert ist (z.B. Anlegen über eine Grid-Zeile).
Ursache
Die Nummer wird erst beim Commit vergeben (createForUI == false). ContextAwareSequenceName.getSequenceName(context) liefert das Kontextobjekt selbst zurück. SequenceIdGenerator.addNames(...) bildet daraus den Diskriminator des Sequenznamens über ((TLObject) id).tId().asString(). Ist der Kontext im selben Commit neu angelegt und damit noch transient, ist tId() == null, und der Aufruf asString() läuft in eine NullPointerException. Die gesamte Speicheroperation wird dadurch zurückgerollt.
Stacktrace (Auszug):
java.lang.NullPointerException: Cannot invoke
"com.top_logic.dob.identifier.ObjectKey.asString()" because the return value of
"com.top_logic.model.TLObject.tId()" is null
at com.top_logic.element.structured.util.SequenceIdGenerator.addNames(SequenceIdGenerator.java:177)
at com.top_logic.element.structured.util.SequenceDefaultProvider.createDefault(SequenceDefaultProvider.java:136)
at com.top_logic.model.factory.TLFactory.setupDefaultValues(TLFactory.java:135)
at com.top_logic.element.layout.grid.GridComponent.storeRowValues(GridComponent.java:1427)
Erwartung
Die kontextabhängige Nummernvergabe soll auch dann funktionieren, wenn das Kontextobjekt in derselben Transaktion erzeugt wird. Da die Nummer ohnehin erst beim Commit vergeben wird, hat das Kontextobjekt zu diesem Zeitpunkt bereits eine ID; der Diskriminator sollte also erst dann aufgelöst werden, wenn dem Kontextobjekt eine ID zugewiesen ist. Alternativ (bzw. für den Fall, dass der Kontext prinzipiell keine ID erhalten kann) sollte statt einer NullPointerException eine aussagekräftige Fehlermeldung ausgegeben werden.