Mit der Extension Library bzw. dem Upgrade Pack 1 ist für XPages eine neue Datasource-Komponente hinzugekommen, die ObjectDataSource. Diese Datasource kann wie die Standard-Datasources für View und Dokument ebenfalls an den verschiedensten Elementen einer XPage angehangen werden, d.h. sowohl an die UIViewRoot der XPage, als auch in Custom Controls, Repeat Controls oder sonstigen Elementen, die eine DataSource verwenden.
Grundlegend gilt für ObjectDataSources, das sie beliebige Java-Objekte beinhalten können, solange die Objekte selbst serialisierbar sind, also das Interface java.io.Serializable implementieren. Hier ein einfaches Beispiel eines Java-Objektes:
package ch.hasselba.extlib.demo; import java.io.Serializable; public class ObjectDataDemo implements Serializable { long timeStamp; public ObjectDataDemo(){ this.update(); } public void update(){ this.timeStamp = java.lang.System.currentTimeMillis(); } public long getTimeStamp() { return timeStamp; } }
Die Java-Klasse ist einfach aufgebaut und liefert den Zeitstempel zurück, der beim letzten Aufruf der update()-Methode gesetzt wurde. Um die Klasse in der XPage verwenden zu können, muss sie nur in einem Source-Folder bereitgestellt sein, der dem Build-Path hinzugefügt wurde bzw. die Klasse im neuen „JavaCode“-Ordner abgelegt sein – eine Modifikation der faces-config.xml ist nicht nötig.
Mittels der createObject-Eigenschaft der ObjectDataSource wird die XPage dazu veranlasst, eine Instanz der Klasse anzulegen, womit das instanzierte Objekte der ObjectDataSource gehört; um die Stabilität einer Applikation nicht zu gefährden und unerwartete Ergebnisse zu provozieren, sollten die Objekte daher nicht anderweitig gespeichert werden (z.B. in Managed Beans o.ä.).
<xp:this.data> <xe:objectData var="objectData1" scope="view" createObject="#{javascript: new ch.hasselba.extlib.demo.ObjectDataDemo();}"> </xe:objectData> </xp:this.data>
Eine ObjectDataSource hat neben dem zu verwendenden scope auch noch die Eigenschaft var, die (wie bei den anderen Datasources auch) den programmatischen Namen darstellt, mit dem die DataSource referenziert werden kann. In diesem Fall ist das Objekt und alle Eigenschaften/Methoden des Objektes über objectData1 zu erreichen:
<xp:label id="label1" value="#{javascript:objectData1.getTimeStamp()}" />
Da z.B. ein Partial Refresh die Datasources nicht jedesmal neuberechnet, muss ein eventuell benötigter Update-Mechanismus selbst implementiert werden. In diesem Beispiel dient dafür die Methode update(), die im Backend aufgerufen werden kann:
<xp:button value="Label" id="button1"> <xp:eventHandler event="onclick" submit="true" refreshMode="partial" refreshId="label1"> <xp:this.action> <![CDATA[#{javascript:objectData1.update()}]]> </xp:this.action> </xp:eventHandler> </xp:button>
[Button ruft die Update-Funktion auf, label1 wird refresht und neuer Zeitstempel angezeigt]
Die ObjectDataSources besitzen eine weitere Eigenschaft namens saveObject. Diese Eigenschaft ist optional und nur erforderlich, wenn man beabsichtigt, auf ein Speichern der DataSources reagieren zu wollen (um z.B. Daten ins Backend zu speichern, o.ä.).
Achtung:
Einige Methodennamen dürfen in der Java-Klasse nicht verwendet werden, da dies sonst zu Problemen mit der bestehenden Architektur kommen kann. Namen wie save() oder load() sind zu vermeiden!