Neuer Fokus in der Großforschung: Feliden statt Higgs-Boson
/RT @TeraEuro
Archive for: ‘Dezember 2011’
Tierpsychologie – Wie tickt der Stubentiger?
Der neue HTTP Header ‘X-XspRefreshId’
Mit Domino 8.5.3 ist der neue HTTP Header ‘X-XspRefreshId’ eingeführt worden, mit dem sich die refreshId eines Partial Refreshs vom Server aus verändern lässt. Dadurch ist es möglich, ein Element zu refreshen, dass Ergebnis dieser Operation jedoch auf ein anderes Element im Client anzuwenden.
Hier ein kleines Beispiel anhand einer XPage, die vor dem Partial Refresh wie folgt aussieht:
Der Code der XPage ist ebenfalls simpel, ausser das bei einem Partial Refresh der XPage ein Header an den Request angefügt wird. Dazu wird das Event afterRestoreView genutzt.
<?xml version="1.0" encoding="UTF-8"?> <xp:view xmlns:xp="http://www.ibm.com/xsp/core"> <xp:this.afterRestoreView><![CDATA[#{javascript: var exCon = facesContext.getExternalContext(); var writer = facesContext.getResponseWriter(); var response = exCon.getResponse(); response.setHeader("X-XspRefreshId", getClientId('label2') ); }]]> </xp:this.afterRestoreView> <xp:button value="Label" id="button1"> <xp:eventHandler event="onclick" submit="true" refreshMode="partial" refreshId="label1"> </xp:eventHandler> </xp:button> <xp:br></xp:br> <xp:br></xp:br> <xp:label value="Label1" id="label1"></xp:label> <xp:br></xp:br> <xp:br></xp:br> <xp:label value="Label2" id="label2"></xp:label> </xp:view>
Der Button löst einen Partial Refresh auf das Label label1 aus, der dazugehörige Request, der an den Server gesendet wird liefert auch den zu erwartenden HTML-Code zurück:
<span id="view:_id1:label1" class="xspTextLabel">Label1</span>
Doch nun kommt der zusätzliche Header ins Spiel. Er bewirkt, dass nicht das label1 ersetzt wird, sondern das Element label2:
Durch den in der HTTP Header in der Antwort des Servers wurde das XSP-Objekt dazu veranlasst, den HTML-Code im DOM-Baum an einer anderen Stelle zu ersetzen.
In diesem kleinen Beispiel tritt ein kleiner Seiteneffekt auf: Das Label mit der id label2 verschwindet komplett aus dem DOM-Baum. Betätigt man den Button ein zweites Mal, funktioniert der Refresh nicht mehr, und folgende Fehlermeldung erscheint im Browser:
Lotus Notes und Domino 8.5.2 Fix Pack 4
Das Fix Pack 4 für Notes und Domino 8.5.2 behebt wieder eine Reihe von Fehlern. Die Installation wird empfohlen, wenn man nicht auf 8.5.3 gehen kann oder möchte.
Corpus Delicti – Das Geheimnis der fünften Tür
Frau Katz hat neulich eine Maus ordnungsgemäß im Schlafzimmer abgeliefert und sich dafür feiern lassen. Die Feier fand statt. Die Maus blieb seitdem verschwunden.
Im fünften Türchen fand sich nun der Corpus Delicti. Seit heute wissen wir, wovon die Maus lebt.
Abbrechen eines Partial Refresh im Client
Leider bietet das XSP-Objekt keine Möglichkeit, einen Partial Refresh via CSJS vorzeitig zu beenden. Zwar basiert der Partial Refresh-Mechanismus auf dojo.xhr-Requests, die diese Funktionalität bieten, doch das XSP-Objekt stellt keine Möglichkeit zur Verfügung, auf die darunter liegenden Dojo-Objekte zuzugreifen.
Um dennoch Zugriff auf die Requests zu erhalten, müssen die Aufrufe von dojo.xhrGet und dojo.xhrPost daher direkt abgefangen und umgebogen werden. Dadurch kann auf das zurück gelieferte dojo.Deferred-Objekt zugegriffen werden und es lassen sich dessen Methoden verwenden.
Hier ein kleines Beispielskript, dass diese Aufgabe verrichtet. Es muss in einen CSJS-Scriptblock eingebettet werden:
var xhrCall = null; dojo.addOnLoad( function(){ /*** hijack dojo's xhrRequest ***/ dojo._xhrPost = dojo.xhrPost; dojo._xhrGet = dojo.xhrGet; dojo.xhrPost = function( args ){ xhrCall = dojo._xhrPost( args ); } dojo.xhrGet = function( args ){ xhrCall = dojo._xhrGet( args ); } });
Will man nun im Client einen Partial Refresh abbrechen, muss nur die cancel-Methode des dojo.Deferred-Objektes aufgerufen werden, und der Partial Refresh wird beendet*:
xhrCall.cancel();
[Die Methode cancel ist unter Dojo 1.3 dokumentiert; in höheren Versionen ist sie aber aus Kompatibilitätsgründen weiterhin vorhanden.]
Das Abbrechen eines Requestes wird allerdings als Partial Refresh-Fehler betrachtet. Um die Popup-Meldung des XSP-Objekts zu unterbinden, muss dem Partial Refresh noch ein eigener Error-Handler mitgegeben werden. Dieser darf ruhig leer sein, er sorgt nur dafür, daß die Fehlermeldung unterdrückt wird:
XSP.partialRefreshGet('id', { onError: function(){} } );
*: Der eigentliche AJAX-Request wird nicht abgebrochen, sondern die weitere Verarbeitung im CSJS unterbunden.
hedersoft xmNavigator – Weiteres Projekt bei OpenNTF
Mit dem hedersoft xmNavigator (XPages Mobile Navigator) steht das nächste OpenNTF Projekt der hedersoft ab sofort kostenlos zur Verfügung. Kurz vor knapp konnte das Projekt noch für den 2. Development Contest von OpenNTF eingereicht werden (danke an alle Beteiligten).
Der hedersoft xmNavigator stellt einen zentralen Einstiegspunkt für mobile Anwendungen auf Smartphones dar. Durch die Nutzung von XPages und JQuery kann die Anwendung auf jedem mobilen Betriebssystem (iOS, Android, ...) genutzt werden.
Weiter Informationen finden Sie hier.
hedersoft xmNavigator – Weiteres Projekt bei OpenNTF
Mit dem hedersoft xmNavigator (XPages Mobile Navigator) steht das nächste OpenNTF Projekt der hedersoft ab sofort kostenlos zur Verfügung. Kurz vor knapp konnte das Projekt noch für den 2. Development Contest von OpenNTF eingereicht werden (danke an alle Beteiligten).
Der hedersoft xmNavigator stellt einen zentralen Einstiegspunkt für mobile Anwendungen auf Smartphones dar. Durch die Nutzung von XPages und JQuery kann die Anwendung auf jedem mobilen Betriebssystem (iOS, Android, ...) genutzt werden.
Weiter Informationen finden Sie hier.
XPages: Stolperfalle Recycling
Gestern hatte ich mal wieder eine schönes „Feature“ gefunden.
Aufgefallen ist dass eine XPage mit einer Null-Pointer Exception abgestürzt ist. Scheinbar war eine View-Datasource, dessen erstes Dokument ich mir holen wollte, nicht vorhanden.
Einige print-outs ergaben dass der Code mehrmals durchlaufen wird, was bei XPages, welche Editable Areas (Callbacks) benutzen, häufiger zu beobachten ist. Allerdings war die View bei Durchlauf 1 bis 3 noch vorhanden, beim 4. Durchlauf hatte es dann geknallt.
Nach vielen Hin und Her testen stand dann die Ursache fest. Ich hatte in einem Custom Control etwas eingebaut, wo auf eine Funktion in einer SSJS-Scriptlibrary aufgerufen wurde. In dieser Funktion wurde eine View referenziert und später wieder recycled. Normalerweise wäre hier kaum ein Zusammenhang zu erkennen. Aber, die Methode und meine XPage benutzten die gleiche View. Scheinbar ist es so, dass Designelemente nicht mehrfach referenziert werden.
D.h. wenn ich an vollkommen unterschiedlichen Stellen z.b. die gleiche View referenziere und auch nur eine davon recycle, dann werden alle Referenzen auf dieses Designelement gelöscht und es regnet entsprechende Null-Pointer Exception.
Die Lösung dieses Problems war denkbar einfach: Wir nahmen einfach das recycling aus dem Code. Normalerweise muss man auch nicht recyclen, da Domino das im Grunde selbst kann. Lediglich bei großen Schleifen wo viele Dokumente durchgeloopt werden sollte man über recycling nachdenken. Auf jeden Fall muss man aber darauf achten wie ich Designelemente referenziere um mir nicht den Ast abzusägen auf dem ich sitze.
Auch das gibt’s: Leere Inbox
Subscription und Extra-Rabatt für DNUG Mitglieder zur Lotusphere 2012 – nur noch heute
DNUG Mitglieder sparen bei der Anmeldung zur Lotusphere 2012 100 USD; sie zahlen als Frühbucher 1.895 USD anstelle der bis dahin regulären 1.995 USD.
Anmeldelink und Buchungscode ...
Diese Konditionen gelten nur noch heute.
YouAtNotes auch 2012 als Aussteller auf der IBM Lotusphere 2012
Bearbeitung von RichTextItems bringt Laufzeitfehler
In diesen Fällen erscheinen Fehlermeldungen wir "Object Variable not set" oder auch "Type mismatch in method AssignClassInstance: AINSTANCE found, Unknown expected"
wenn man mit dem Body Feld der Kalendermaske mit folgendem Code:
Sub Click(Source As Button)
Dim s As New NotesSession
Dim ws As New NotesUIWorkspace
Dim uiDoc As NotesUIDocument
Dim doc As NotesDocument
Dim body As NotesRichTextItem
Dim rtnav As NotesRichTextNavigator
' - Get UI and BE document handles to current document
Set uiDoc = ws.CurrentDocument
Set doc = uiDoc.Document
' - Create or grab RT item
If doc.IsNewNote Then
doc.Form = "RT Tests"
Set body = New NotesRichTextItem(doc,"Body")
Else
Set body = doc.GetFirstItem("Body")
End If
' - Create a 4 column table in RT item
Dim styles(1 To 4) As NotesRichTextParagraphStyle
rowCount% = 5
columnCount% = 4
'Column 1
Set styles(1) = s.CreateRichTextParagraphStyle
styles(1).LeftMargin = 0
styles(1).FirstLineLeftMargin = 0
styles(1).RightMargin = RULER_ONE_CENTIMETER* 2
'Column 2
Set styles(2) = s.CreateRichTextParagraphStyle
styles(2).LeftMargin = 0
styles(2).FirstLineLeftMargin = 0
styles(2).RightMargin = RULER_ONE_CENTIMETER* 17
'Column 3
Set styles(3) = s.CreateRichTextParagraphStyle
styles(3).LeftMargin = 0
styles(3).FirstLineLeftMargin = 0
styles(3).RightMargin = RULER_ONE_CENTIMETER* 3
'Column 4
Set styles(4) = s.CreateRichTextParagraphStyle
styles(4).LeftMargin = 0
styles(4).FirstLineLeftMargin = 0
styles(4).RightMargin = RULER_ONE_CENTIMETER* 2.5
Call body.AppendTable(rowCount%, columnCount%,,,styles)
' - Populate table - the top row
Set rtnav = body.CreateNavigator
Call rtnav.FindFirstElement(RTELEM_TYPE_TABLECELL)
Call body.BeginInsert(rtnav)
Call body.AppendText("Nr.")
Call body.EndInsert
Call rtnav.FindNextElement(RTELEM_TYPE_TABLECELL)
Call body.BeginInsert(rtnav)
Call body.AppendText("Thema")
Call body.EndInsert
Call rtnav.FindNextElement(RTELEM_TYPE_TABLECELL)
Call body.BeginInsert(rtnav)
Call body.AppendText("Erlediger")
Call body.EndInsert
Call rtnav.FindNextElement(RTELEM_TYPE_TABLECELL)
Call body.BeginInsert(rtnav)
Call body.AppendText("Zeit")
Call body.EndInsert
Call body.Update
' - Reopen document in order to load RT item into UI
doc.SaveOptions = "0" ' make it possible to close the document without a "do you want to save" prompt.
Call uidoc.Close(True)
Set uidoc = ws.EditDocument(True, doc, , , , True)
Call uidoc.Document.RemoveItem("SaveOptions")
End Sub
arbeitet.
Nach langer Analyse stellte ich fest, das die Ursache für den Laufzeitfehler (für mich nicht erklärbar) in der Definition der Feldhilfe
zu finden ist. Entfernt man diese, so wird mit
Set body = doc.GetFirstItem("Body")
auch das entsprechende Item gefunden.
Bearbeitung von RichTextItems bringt Laufzeitfehler
In diesen Fällen erscheinen Fehlermeldungen wir "Object Variable not set" oder auch "Type mismatch in method AssignClassInstance: AINSTANCE found, Unknown expected"
wenn man mit dem Body Feld der Kalendermaske mit folgendem Code:
Sub Click(Source As Button)
Dim s As New NotesSession
Dim ws As New NotesUIWorkspace
Dim uiDoc As NotesUIDocument
Dim doc As NotesDocument
Dim body As NotesRichTextItem
Dim rtnav As NotesRichTextNavigator
' - Get UI and BE document handles to current document
Set uiDoc = ws.CurrentDocument
Set doc = uiDoc.Document
' - Create or grab RT item
If doc.IsNewNote Then
doc.Form = "RT Tests"
Set body = New NotesRichTextItem(doc,"Body")
Else
Set body = doc.GetFirstItem("Body")
End If
' - Create a 4 column table in RT item
Dim styles(1 To 4) As NotesRichTextParagraphStyle
rowCount% = 5
columnCount% = 4
'Column 1
Set styles(1) = s.CreateRichTextParagraphStyle
styles(1).LeftMargin = 0
styles(1).FirstLineLeftMargin = 0
styles(1).RightMargin = RULER_ONE_CENTIMETER* 2
'Column 2
Set styles(2) = s.CreateRichTextParagraphStyle
styles(2).LeftMargin = 0
styles(2).FirstLineLeftMargin = 0
styles(2).RightMargin = RULER_ONE_CENTIMETER* 17
'Column 3
Set styles(3) = s.CreateRichTextParagraphStyle
styles(3).LeftMargin = 0
styles(3).FirstLineLeftMargin = 0
styles(3).RightMargin = RULER_ONE_CENTIMETER* 3
'Column 4
Set styles(4) = s.CreateRichTextParagraphStyle
styles(4).LeftMargin = 0
styles(4).FirstLineLeftMargin = 0
styles(4).RightMargin = RULER_ONE_CENTIMETER* 2.5
Call body.AppendTable(rowCount%, columnCount%,,,styles)
' - Populate table - the top row
Set rtnav = body.CreateNavigator
Call rtnav.FindFirstElement(RTELEM_TYPE_TABLECELL)
Call body.BeginInsert(rtnav)
Call body.AppendText("Nr.")
Call body.EndInsert
Call rtnav.FindNextElement(RTELEM_TYPE_TABLECELL)
Call body.BeginInsert(rtnav)
Call body.AppendText("Thema")
Call body.EndInsert
Call rtnav.FindNextElement(RTELEM_TYPE_TABLECELL)
Call body.BeginInsert(rtnav)
Call body.AppendText("Erlediger")
Call body.EndInsert
Call rtnav.FindNextElement(RTELEM_TYPE_TABLECELL)
Call body.BeginInsert(rtnav)
Call body.AppendText("Zeit")
Call body.EndInsert
Call body.Update
' - Reopen document in order to load RT item into UI
doc.SaveOptions = "0" ' make it possible to close the document without a "do you want to save" prompt.
Call uidoc.Close(True)
Set uidoc = ws.EditDocument(True, doc, , , , True)
Call uidoc.Document.RemoveItem("SaveOptions")
End Sub
arbeitet.
Nach langer Analyse stellte ich fest, das die Ursache für den Laufzeitfehler (für mich nicht erklärbar) in der Definition der Feldhilfe
zu finden ist. Entfernt man diese, so wird mit
Set body = doc.GetFirstItem("Body")
auch das entsprechende Item gefunden.