Mittwoch, 22. September 2010

Browser Quirk - Deselect Radiobuttons





Wir haben 2 Gruppen von Radiobuttons.
Wenn die erste Gruppe auf Nein gestellt ist, so muss die zweite Gruppe deselectiert werden. Hierzu gibt es gleich mehrer Dinge zu beachten. Da sich der IE und der FF in diesem Punkt voneinander unterschiedlich verhalten

  1. Die Buttons (Gruppe 1) benötigen unbeding onclick="this.blur()" . Damit der Internetexplorer auf die Veränderung reagiert.

  2. Fehlerhafte indexierung der Buttons im IE.





Definition der steuernden Buttons.
<input type="radio" onclick="this.blur()"
onchange="de_wwag_alma_anliegen_versicherungsfallchanged(this.value)"
value="true"
name="editForm:versicherungsfallJaNeinRadio">

<input type="radio" onclick="this.blur()"
onchange="de_wwag_alma_anliegen_versicherungsfallchanged(this.value)"
value="false"
name=":editForm:versicherungsfallJaNeinRadio" >



Deselektieren der abhängigen Buttons.

document.getElementsByName("view<portlet:namespace/>:editForm:versicherungsfallAltNeuRadio")[0].checked = false;
//This is a Browser Quirk - we only have 2 option
//In FF the indexes are 0 and 1
//In IE 0 and 2
document.getElementsByName("editForm:versicherungsfallAltNeuRadio")[0].checked = false;
document.getElementsByName("editForm:versicherungsfallAltNeuRadio")[1].checked = false;
document.getElementsByName("editForm:versicherungsfallAltNeuRadio")[2].checked = false;

Donnerstag, 9. September 2010

Tomcat Authentication: Wie zeige ich den Grund für einen Authentifizierungsfehler an?

Im Tomcat bietet es sich an, die J2EE Authentifizierung für geschützte Resourcen zu verwenden. Das Verfahren ist recht simpel einzurichten und wird auf vielen Seiten im Internet erklärt, z.B. hier.

Diese Einfache Methode der Authentifizierung leitet den User auf eine Login-Seite, falls er eine geschützte Resource aufrufen möchte, aber noch nicht angemeldet ist. Auf dieser Login-Seite wird ein Formular angezeigt, in das er Username und Passwort eingeben muss.


Schlägt die Authentifizierung aus irgend einem Grund fehl, wird der User auf die in der web.xml eingestellte Error-Seite weitergeleitet. In den meisten Anwendungen ist die Error-Seite die Login-Seite mit einem Hinweistext, dass die Authentifizierung nicht möglich war. Manchmal wird noch ein Link angeboten, über den der User sein Passwort zurücksetzen kann.

Bsp:


Das Problem ist jedoch, dass es auch andere Gründe für eine fehlgeschlagene Anmeldung geben kann, außer dass Username oder Passwort falsch eingegeben wurden:

  • Passwort ist abgelaufen.

  • Passwort wurde zu oft falsch eingegeben.

  • Konto wurde wegen Inaktivität gesperrt.

  • u.s.w.


Diese Informationen können dem User jedoch bei Verwendung der Standard-Authentifizierung nicht angezeigt werden.

Abhilfe schafft hier die Implementierung eines eigenen Valves zur Form-Authentifizierung. Die Klasse muss von org.apache.catalina.authenticator.FormAuthenticator abgeleitet werden (ganz richtig, das ist eine Tomcat-spezifische Klasse!). In dieser Klasse wird die Methode forwardToErrorPage() überschrieben. Die Methode wird vom Tomcat aufgerufen, nachdem die Authentifizierung fehlschlug und der User zur Error-Seite geleitet wird.

Eine Beispiel-Implementierung:

public class CustomFormAuthenticator extends FormAuthenticator {

@Override
protected void forwardToErrorPage(Request request, Response response,
LoginConfig config) throws IOException {
Integer errorReason = checkOutErrorReason();

request.setAttribute("loginErrorReason", errorReason);
super.forwardToErrorPage(request, response, config);
}

protected void checkOutErrorReason() {
//TODO hier die Ermittlung der Ursache für die
// abgelehnte Authentifizierung implementieren
return null;
}

}

In diesem Beispiel wird ein Request-Parameter gesetzt (loginErrorReason), der dann in der Error-Page ausgewertet werden kann.
Bsp.:

Integer errorReason = (Integer) request.getAttribute("loginErrorReason");


Wichtig ist, dass der CustomFormAuthenticator in einem jar im Tomcat/lib-Verzeichnis deployt wird, damit der Tomcat die Klasse findet.

Das Valve muss dann dem Tomcat noch in der Konfiguration im Context der Web-Anwendung (in server.xml) mitgeteilt werden:

...
<Context docBase="myapp" path="" reloadable="true">
<Valve className="custom.auth.CustomFormAuthenticator" />
</Context>
...


Eine andere Möglichkeit der Konfiguration besteht in der Web-Anwendung in der Datei META-INF/context.xml:

<Context>
<Valve className="custom.auth.CustomFormAuthenticator" />
</Context>

Donnerstag, 5. August 2010

Danamische AJAX-Tabelle

Basis-Tabelle

<div id="ScrollElement" onscroll="nextElements()"
style="height: 100px; width: 300px; overflow: auto; border: solid 1px black;">
<table id="tableElement" >
<thead>
<tr>
<th>Item Name</th>
</tr>
</thead>
<tbody>
<tr><td>Item</td></tr>
<tr><td>Item</td></tr>
<tr><td>Item</td></tr>
<tr><td>Item</td></tr>
<tr><td>Item</td></tr>
<tr><td>Item</td></tr>
<tr><td>Item</td></tr>
<tr><td>Item</td></tr>
<tr><td>Item</td></tr>
<tr><td>Item</td></tr>
<tr><td>Item</td></tr>
<tr><td>Item</td></tr>
<tr><td>Item</td></tr>
<tr><td>Item</td></tr>
<tr><td>Item</td></tr>
<tr><td>Item</td></tr>
</tbody>
</table>
</div>
<span id='Debug'></span>


Javascriptcode

<script type="text/javascript">
var global_block = false;
var global_counter = 0;

function nextElements()
{
var element = document.getElementById('ScrollElement');
var height = element.scrollHeight;
var scroll = element.scrollTop;

var diff = height - scroll;

document.getElementById('Debug').innerHTML = diff;

if(diff <= 200 && global_block == false)
{
global_block = true;
appendNewElements();
}
}

function appendNewElements()
{
for(var i=0; i<10; i++)
{
global_counter++;

var newListElement = document.createElement('tr');

var tdelement = document.createElement('td');

var newtext=document.createTextNode('Martin' + global_counter);

tdelement.appendChild(newtext);

newListElement.appendChild(tdelement);

//newListElement.innerHTML = 'AppendedItem: ' + global_counter;

var parentElement = document.getElementById('tableElement').getElementsByTagName("TBODY")[0];

parentElement.appendChild(newListElement);


newListElement = null;
tdelement = null;
newtext = null;
parentElement = null;
}
global_block = false;
}
</script>


Anmerkung.

Dieses Basiskonstrukt läuft im sowohl im Internetexplorer (7) als auch im neuesten Chrome.

Mittwoch, 4. August 2010

JSF ComboBoxen mit Autopostback

Um Dynamische GUIs zu bauen gibt es verschieden Optionen die GUI zu verändern.
In den meisten JSF-Einführungenwird zwar beschrieben wie man ein SelectOne verwendet, jedoch nicht wie man eine Bestimmte logik im Backing bean anspricht.




<h:selectOneMenu id="selectCar" value="#{carBean.currentCar}">
<f:selectItems value="#{carBean.carList}" />
</h:selectOneMenu>


Der Entscheidende Punkt ist, dass 2 Attribute gesetut werden müssen.
das onchange="this.form.submit()" bewirkt, dass die Werte des Formulars ins Model übernommen werden (durch Aufruf der setter-Methode).
Die Business-Logik sollte man aber nicht in den Setter reinbauen. Sondern sollte mittels eines valueChangeListener eingebunden werden.


<h:selectOneMenu id="selectCar" value="#{carBean.currentCar}"
valueChangeListener="#{BackingBean.processValueChange}"
onchange="this.form.submit()"
>
<f:selectItems value="#{carBean.carList}" />
</h:selectOneMenu>



public void  proessValueChange(ValueChangeEvent event) {
//some logic
}

Mittwoch, 28. Juli 2010

Checklist - HTML-Tuningtips


  • Unterbinung von Automcomplete. autocompletet="off"
  • Bei Datumsfeldern size="10 und maxlength="10"
  • style="text-align: left; padding 2px 2px 2px 20px"

Donnerstag, 22. Juli 2010

DB2-Batch-Processing-Script

Manchmal sind die Datenmengen so groß, dass eine Sinnvolle verarbeitung nur noch
mittels der db2-Console funtktioniert. Die Anderen Tools die wir verwendet haben konnten mit dem ca. 80MB großen File nichts mehr anfangen.

Außerdem ist das db2cmd ein Tool, dass den DB2-Administratoren vertraut ist.

Wir haben ein script batch.cmd gebaut, dass wir unseren Administratoren zukommen lassen können.


db2 connect to mydbname user myuserid using mypasswd
db2 -vf mybigsqlfile.sql -z readme.txt


Unser File hatte noch den Schönheitsfehler, dass das Encoding UTF-8 war.
Das dB2 ist so doof und unterstellt, dass das Encodung des inputfiles (hier mybisqlfile.sql) das gleiche Encoding besitzt.

Sie haben 2 Möglichkeit dem Abhilfe zu schaffen.

  1. Ein File mit dem richten Encoding erzeugen.

  2. Das Encoding mittels eines Tools convertieren.

Sprechende JSF-Fehlermeldungen

Leider bekommt man ab und an Fehler in den Anwendungen gemeldet.
Meist hilft ein aussagekräftiger Screenshot weiter.
Normalerweise fängt man nun an in seinen Log-Files zu forschen.
- Wenn man überhaupt an diese einfach rankommt.
Viel einfacher ist es, wenn im Screenshot die Fehlermeldung schon eingebaut ist.

Bei der JSF-Programmierung gibt es den <h:messages>-Tag.



<h:messages> ..... showDetail="true"
</h:messages>




In diesem Tag sollte man das showDetail-Attribut auf true setzen. Dann bekommt man eine sprechende Meldung.


Fehlermeldung mit showDetail="false"





Fehlermeldung mit showDetail="true"