Dienstag, 25. Mai 2010

Zugang zum WLAN der Uni Bielefeld mit Android

Hier eine kurze Anleitung, wie man das Nexus One mit Android 2.2 (aka Froyo) ins WLAN der Uni bringt. Ist eigentlich genauso geblieben wie unter Android 2.1

[Update: Die inzwischen verfügbare Anleitung des HRZs wurde unten ergänzt und in den Kommentaren finden sich Beschreibungen für alle möglichen älteren und neueren Android Versionen. Für neue Versionen von Android sind gerade die komplizierten Schritte des folgenden Verfahrens nicht mehr notwendig]:Flieg, Vogel, flieg

  1. Grundsätzlich finden sich in der guten Beschreibung des HRZs alle notwendigen Infos, allerdings heute noch nicht zugeschnitten auf Android.
  2. Von der Seite des DFN Vereins das Wurzelzertifikat Deutsche Telekom Root CA 2 installieren. Dazu mit dem Android Browser auf den Link zum .crt-Format gehen. Das Zertifikat wird zur Installation angeboten, dabei muss man einen Namen vergeben (z. B. Telekom Root CA 2) und – falls noch nie verwendet – dem Android Anmeldeinformationsspeicher ein Passwort verpassen.
  3. Unter den globalen Einstellungen (erreichbar durch Wählen der Menü-Taste in einer der Homescreens) in die erste Option ‘Drahtlos & Netzwerke’ gehen
  4. Dort wiederum in die ‘WLAN-Einstellungen’. Ggf. WLAN noch aktivieren, falls es ausgeschaltet sein sollte.
  5. Das Handy ermittelt die verfügbaren WLAN Netzwerke. Darunter sollte auch ‘ubi’ sein.
  6. ‘ubi’ wählen und wie folgt konfigurieren:
    • EAP-Methode: PEAP
    • CA-Zertifikat: Das gerade installierte ‘Telekom Root CA 2’ Zertifikat auswählen
    • Nutzerzertifikat: bleibt leer
    • Identität: Der HRZ Benutzername. Ohne @uni…. und so weiter, nur der nackte Name
    • Anonyme Identität: bleibt leer
    • Passwort: das HRZ Passwort
Voilá, der Androide sollte nun in wenigen Sekunden online gehen.

Inzwischen gibt es vom HRZ eine Videoanleitung zur Einrichtung des WLANs auf einem Android Gerät mit 4.* Version:

Dienstag, 16. März 2010

Unboxing the Nexus One – Erste Schritte mit dem Google Handy und Android 2.1

Gestern war es endlich so weit: Nach acht langen Wartetagen wurde das aus den USA georderte Nexus One von DHL Boten an der Haustüre abgeliefert. In diesem Blogeintrag will ich die ersten Schritte mit dem Google Phone beschreiben. Da das Nexus One die zur Zeit modernste Android Version 2.1 mitbringt ist so eine Beschreibung vielleicht auch für andere interessant.

Unboxing

Wenn man sich vor dem Öffnen des Kartons einen Moment Zeit nimmt, so sieht man auf fast allen Paketseiten Aufkleber. Sie dokumentieren die weite Reise, die es schon zurück gelegt hat. Angefangen mit einem Container Code, der wohl vom Transfer vom taiwanesischen Hersteller HTC in die USA stammt, über ein FedEx Label bis hin zum DHL Zettel und den von Borderlinx ausgestellten Transferpapieren.Lieferkartons Nexus One und Docking StationMein Paket enthielt neben dem Nexus One auch noch eine Dockingstation, daher war das Päckchen etwas größer. Die Dockingstation schien mir eine gute Idee zu sein, da der Energieverbrauch dieser Smartphones mich stark an meinen alten Tungsten Palmtop erinnerte. Der schätzte es auch sehr jeden Abend wieder geladen zu werden. Und tatsächlich ist der Ladestatus meines Nexus One nach einem Tag der Herumspielerei schon ziemlich abgesackt. Zur Dockingstation gehört übrigens auch ein Kabel um das Nexus an die HiFi Anlage anzuschließen.

Handy und Dockingstation kommen in schönen, stabilen weißen Kartons daher, die eigentlich viel zu Schade zum Wegwerfen sind. Macht man sich daran den schlanken Nexus One Karton auszupacken, so findet man die bei einem Handy üblichen Bestandteile vor:

Inhalte des Nexus One KartonsIm Uhrzeigersinn: Drei kleine Booklets mit Sicherheitshinweisen etc.; eine Neopren Hülle mit Android Logo; die Batterie; Kopfhörer samt Pads; USB Kabel; Ladekabel.

Coming to life: Laden

Am Anfang – wie immer bei einem neuen Mobilgerät – muss natürlich nun erst einmal die Batterie geladen werden. Eine echte Geduldsprobe. Beim Einsetzen der Batterie kann man auch gleich seine SIM Karte einbauen. Der Einbau der Batterie wird in den Booklets beschrieben, geöffnet wird das Handy an der Rückseite durch Hochschieben des Teils der Abdeckung, die auch die Kamera schützt.

Das Laden erfolgt immer über die Mini-USB Buchse und kann entweder durch das mitgelieferte Netzteil erfolgen, über die Dockingstation oder auch über das USB Kabel. Für die Verwendung des Netzteils und der Dockingstation (die übrigens ein völlig identisches Netzteil enthält) muss man noch einen Adapter zur Hand haben, um die flachen US-Stecker sicher in die hiesigen Steckdosen zu bekommen:Nexus One Ladegerät mit Adapter

In meinem Fall lag so ein Adapter noch von einer Lumix Kamera herum, es konnte also sofort losgehen. Falls gerade kein solcher Adapter zur Hand ist kann wie gesagt das USB Kabel an einem Computer genutzt werden.

Den Ladevorgang zeigt eine kleine Leuchte auf der Vorderseite an, die zuerst orange ist und später grün wird. Auch wenn in meinem Fall die Batterie offenbar in gewissem Umfang vorgeladen war – das Nexus One meldet sich nach dem Einsetzen sofort mit dem Startbildschirm – habe ich dem Gerät dann doch erst zwei Stunden an der Ladebuchse gegönnt.

On Air – Den Androiden online bringen

Sobald also genug Batteriepower vorhanden ist muss spätestens jetzt die SIM Karte eingesetzt werden. Hoffentlich verbunden mit einer Datenflatrate, sonst könnte es am Ende teuer werden:) Nach dem Einschalten begrüßt uns der kleine Androide und man wählt im ersten Schritt die Sprache aus:Android 2.1 Startbildschirm Erfreulicherweise ist auch ‘Deutsch’ in der Auswahl vorhanden und alle mir bisher begegneten Texte sind perfekt übersetzt.

In den folgenden Schritten kann man ein paar Hilfestellungen lesen bis man zum entscheidenden Schritt kommt: Der Anmeldung beim Google Konto. Ohne Google Konto ist mit Android nichts anzufangen. Wer noch keines besitzt kann sich vielleicht einfacher eines über einen normalen PC anlegen, an statt die Schritte auf dem Handy zu absolvieren. Natürlich muss für die Anmeldung auch eine Datenverbindung über das Telefonnetz vorhanden sein.

Für diejenigen, die wie ich ihre eMail, Kontakte und Kalender bei Google abgelegt haben, ist mit der Anmeldung am Google Konto die Einrichtung des Nexus One eigentlich schon zu einem großen Teil erledigt: Das Nexus One beginnt unmittelbar mit der Synchronisation z. B. der Kontakte. Je nachdem, wie viele Daten dabei hin und her geschaufelt werden müssen kann dies länger oder kürzer dauern. Bei mir hat es nur wenige Minuten gedauert.

Wichtiger Tipp: In der Voreinstellung, die man bei der ersten Einrichtung des Handys auch nicht ändern kann, werden alle Kontakte aus dem GMail Konto synchronisiert. Auch solche, die nur aus einer eMailadresse bestehen! Wer GMail schon etwas länger nutzt hat hier schnell hunderte bis tausende von ‘Kontakten’, die auf dem Nexus One reichlich überflüssig sind. Man sollte daher sofort (noch vor dem Ende der Synchronisation) in die Einstellungen wechseln und beim Synchronisieren die Option wählen, durch welche nur Kontakte mit Telefonnummer übertragen werden. Das reduziert die Kontakte wesentlich. Beim Schreiben von eMails stehen die übrigen Adressen natürlich weiterhin zur Verfügung.

Erstes Tuning – Multitouch, Screenlock und W-LAN

Das Nexus One ist nun grundsätzlich betriebsbereit und all die spannenden Anwendungen wie Maps, Goggles und so weiter sind verfügbar. Hier nur noch drei Dinge, die ich für wichtig halte:

Updates: Schon kurz nach dem Start kommt eine Meldung zu einem verfügbaren Betriebssystemupdate rein (sichtbar in der Leiste am oberen Rand). Mit diesem Update werden erst die Multitouch Funktionen aktiv, wegen denen Apple gerade HTC verklagt hat. Eine wichtige Funktion, die man nicht mehr missen möchte, wenn man sie erst einmal kennen gelernt hat. Also nicht lange mit der Installation warten (aber vielleicht vorher noch den Punkt zur W-LAN Einrichtung lesen). Am kommenden Tag kam dann bei mir noch ein Update für die Google Maps, welches mir auch wichtig erschien.

Screenlock: Damit ein Android Handy funktionieren kann muss es – wie beschrieben – das eigene Google Passwort kennen. Und schnell sammeln sich noch weitere Passworte auf dem kleinen Schmuckstück, zum Beispiel das Facebook Passwort (die App ist schon vorinstalliert). Es ist daher bei so einem Gerät noch wichtiger zumindest einen minimalen Schutz gegen unbefugte Verwendung einzurichten. Am einfachsten geht dies über das Setzen eines visuellen Schlüssels: In den Einstellungen unter Standort und Sicherheit wird das sogenannte Display-Entsperrungsmuster eingeschaltet und gesetzt. Zum Entsperren des Nexus One fährt man dann ein selbst festgelegtes Muster auf dem Bildschirm nach. Dies ist kein hundertprozentiger Schutz – allein die Wischspuren auf dem Display können schon die Lösung verraten – aber besser als ein völlig offenes Handy.Nexus One in Dockingstation mit HiFi Kabeln

W-LAN: Wer nicht zu den Glücklichen gehört, die eine unbegrenzte Datenflatrate ihr Eigen nennen können, wird als einen weiteren sehr frühen Schritt die W-LAN Einrichtung vollziehen. Über W-LAN können auch die oben beschriebenen Updates schnell durchgeführt werden. Bei mir war die Verbindung zum heimischen T-DSL mit einem Speedport überhaupt kein Problem. Das W-LAN der Uni Bielefeld war hingegen bisher noch eine nicht zu knackende Nuss. Sobald mir dort der Zugriff gelungen ist werden ich dazu noch einen separaten Text verfassen. Übrigens: Falls man Angst vor hohen Kosten durch ungewünschte Datenverbindungen über das Telefonnetz hat, dem sei der Flugmodus als Tipp genannt. Dieser lässt sich über die Einstellungen unter Drahtlos und Netze setzen und verhindert den Aufbau aller Arten von drahtlosen Verbindungen.

Und alles weitere ergibt sich dann von selbst:)

Ach ja: Die Seite mit der Beschreibung, wie man das Nexus One heute schon in Deutschland ordern kann, findet man hier.

Dienstag, 16. Februar 2010

Operas neue Browserversion: Die Chrome Saat geht auf

Am 11. Februar veröffentlichte die norwegische Browserschmiede Opera Software ASA die neue Version 10.50 Beta ihres Opera Webbrowsers. Und während noch in der Pressemittelung nur davon die Rede war, dass die neue Version viel schneller sei als die vorherigen, wird inzwischen auf der Downloadseite vom ‘schnellsten Browser der Welt’ gesprochen. Unabhängige Seiten wie Computerworld bestätigen diese Behauptung durch Vergleiche mit dem SunSpider Javascript Benchmark. Aber was hat das Ganze mit dem Google Browser ‘Chrome’ zu tun?

Die Quantensprünge der alternativen Browser

Zunächst: Was sind die alternativen Browser? Dies sind all die Webbrowser, die nicht der Microsoft Internetexplorer sind. Denn der MSIE, wie er im Folgenden abgekürzt wird, ist weiterhin der unangefochtene Platzhirsch im Browsergeschäft. Und alle anderen sind damit nur ‘Alternativen’, selbst wenn der Marktanteil des MSIE offenbar stetig bröckelt.

Seit dem Jahr 2008 haben alle ‘alternativen Browser’ enorme Performancesprünge vollzogen, insbesondere im Bereich der Javascript Leistung. Hier die entsprechenden Meldungen:

  • Firefox: Die Pressemitteilung zur Version 3.5 vom 30.06.2009 spricht davon, dass die neue Version ‘zweimal schneller als die Version 3’ sei und eine ‘stark gesteigerte JavaScript-Performance’ aufweise. Mit der Version 3.5 wurde die Tracemonkey Engine eingeführt
  • Safari: Apple behauptet heute weiterhin, dass Safari mit seiner Nitro Engine der schnellste Webbrowser sei. Diese neu entwickelte Engine wurde mit der Version 4 eingeführt, laut PCTipp soll sie ’Javascript bis zu 4.5 Mal schneller ausführen’ als die Version 3. Die Meldung datiert aus dem Juni 2009.
  • Opera: Der Vollständigkeit halber noch einmal die Pressemitteilung zur Version 10.50 Beta: ‘more than eight times faster than its predecessor’ soll der Browser durch die neue Carakan Engine sein

Woher kommen plötzlich diese enormen Geschwindigkeitssteigerungen, die nicht nur behauptet, sondern real sind? Den Anstoß dazu hat mit Sicherheit Google mit der überraschenden Veröffentlichung des eigenen Chrome Browsers im September 2008 geben. Hier ein Video von Google zur Einführung:

Der Chrome Browser brachte ebenfalls seine eigene Javascript Engine mit, die V8 genannt wird. In der englischen Wikipedia ist nachzulesen, dass Chrome mit der Version 1.0 sofort an die Performancespitze vorstieß und quasi unmittelbar zu Reaktionen der anderen Browserhersteller führte. Die nächsten Versionssprünge brachten dann jeweils noch weitere Geschwindigkeitssteigerungen. Mit Chrome begann daher das Rennen um die Krone bei der Javascript Performance, welches noch heute anhält.

Googles Ziele werden in jedem Fall erreicht

Angesichts der Behauptungen mindestens von Apple und Opera die jeweils schnellsten Browser der Welt im Angebot zu haben, und dem immer noch besseren Abschneiden von Chrome bei bestimmten Tests wie der V8 Benchmark Suite: welche Rolle spielt es eigentlich, wer wirklich den schnellsten Webbrowser  anbietet? Für Google spielt es vermutlich keine Rolle!

Selbst wenn Chrome nie der Browser werden wird, für den sich die Mehrheit der Internetnutzer entscheidet, so hat Google durch Chrome doch den behäbig gewordenen Anbietern der alternativen Browser, die sich immer nur mit den vorsintflutlichen Produkten Microsofts verglichen hatten, einen ordentlichen Tritt gegeben. Wann hat es in den Jahren zuvor jemals eine so intensive Phase von Innovationen in diesem Bereich gegeben?

Und all diese Innovationen sorgen nur dafür, dass webbasierte Anwendungen wie die Google Apps noch besser nutzbar werden, noch mehr Funktionen erhalten können und damit die Idee noch mehr Überzeugungskraft gewinnt, alle Dienste und Anwendungen ins Web zu verlagern. Und das Web ist nun mal die Stelle, an der Google sein Geld verdient.

Es geht Google daher mit Chrome vermutlich nicht wirklich darum mittel- oder langfristig, schon gar nicht kurzfristig, zum Marktführer unter den Browseranbietern zu werden. Die Häme, die über Google nach dem langsamen Start von Chrome immer mal wieder ergossen wurde, war daher viel zu kurzsichtig: Chrome ist im wesentlichen die Saat, die bei den anderen Browserherstellern ausgesät wurde, und schon nach eineinhalb Jahren hat sie überall gekeimt und die erwarteten Früchte getragen. Nur noch nicht beim Marktführer:

Und was macht der Marktführer?

Microsoft, als vermutlich sowohl ungeliebtester wie auch größter Browseranbieter, hat sich bisher nicht dem großen Rennen angeschlossen und steht heute in Bezug auf Performance, Funktionalität und Standardkonformität ganz am Ende. Hat die Chrome Saat hier noch keine Wurzeln schlagen können?

Die Vermutung liegt nahe, dass Microsoft in webbasierten und womöglich auch noch kostenlosen Diensten wie den Google Apps oder Zoho eine Bedrohung seiner Geldkühe wie dem Office Paket gesehen hat und diese Entwicklung auf keinen Fall durch einen zu performanten und schon mit Windows mitgelieferten Webbrowser fördern wollte. Möglicherweise hat man in Redmond auch die Dynamik dieser neuen Dienste unterschätzt, insbesondere wenn sie von mächtigen Gegenspielern wie Google forciert werden, die gar nicht darauf angewiesen zu sein scheinen, von ihren Nutzern für mit jedem Tag leistungsfähiger werdende Dienste Geld zu verlangen.

Doch selbst Microsoft geht inzwischen mit Produkten wie Sharepoint oder Office Live den Weg ins Web und dabei wird es allmählich peinlich, wenn man den Kunden für eine optimale Performance empfehlen muss irgendeinen Webbrowser zu nehmen, aber auf keinen Fall den, der vom eigenen Haus angeboten wird. Ein Übriges wird vermutlich die Auflage der EU tun, die Microsoft dazu zwingen wird den Nutzern von MS Windows eine Möglichkeit zur Wahl des Webbrowsers einzurichten.

Und in der Tat scheint Microsoft mit der kommenden Version 9 des MSIE wieder zur Konkurrenz aufschließen zu wollen: In dem IEBlog findet sich ein Artikel, der Charts mit Performancevergleichen zu früheren IE Versionen und zu den Konkurrenten enthält. Demnach ist der IE9 immer noch langsamer als die Alternativen, aber nicht mehr viel. Und er ist ja noch in einem frühen Stadium.

Was weiter

Wie es aussieht scheint die Chrome Saat tatsächlich an allen Stellen aufzugehen. In jedem Fall wird der wieder intensivierte Browserkrieg noch weiter gehen und diese schön illustrierte History of Web Browsers noch lange fortgeführt werden können.

Donnerstag, 11. Februar 2010

Die Schwierigkeit einer guten Sicherheitsabfrage im Zeitalter sozialer Netzwerke

Während man sich, so nach und nach, bei allen erdenklichen sozialen Netzwerken, Internetshops, Finanzdienstleistern und bald auch beim Friseur nebenan digitale Identitäten zusammen klickt, steht man am Anfang immer wieder vor den gleichen Fragen:

  1. Welchen Benutzernamen soll ich mir geben?
  2. Welches Passwort ist in diesem Fall sicher genug?
  3. Was passiert, wenn ich Benutzername oder Passwort (oder beides) vergessen habe?

Frage 1 ist heute meist leicht zu beantworten, da als Benutzername in vielen Webseiten Schlüssel einfach die eMailadresse verwendet wird (wer mehr als eine eMailadresse hat: selbst Schuld:). Frage 2 ist potentiell kompliziert und wird daher von den meisten wohl mit ‘Ich verwende überall das gleiche Passwort’ beantwortet, vielleicht noch mit einer Variation zwischen einem Passwort für ganz wichtige Seiten und einem für den Rest.

Frage 3 hingegen bietet den meisten Spielraum: Hier finden sich alle möglichen Verfahren, die sich im Kern darum drehen, dass man als armer, vergesslicher Tropf einer anonymen, auf anderen Seite der Erdkugel beheimateten Webseite beweisen muss, dass man ICH ist. Wobei man mit dieser Webseite nie mehr Verkehr hatte als über ein paar Mausklicks und die Eingabe einiger Angaben (Name, Adresse, Konto), die diese Webseite vielleicht nie geprüft hat.

Da man nicht bei allen Seiten nach dem Verfahren ‘Passwort vergessen? Ist mir egal, ich lege mir einfach ein neues Login zu…’ verfahren kann muss man sich zwangläufig mit dieser Frage beschäftigen. Und ein Verfahren, welches einem dabei immer wieder begegnet, ist die Sicherheitsfrage.

Was ist die Idee der Sicherheitsfrage?

Bei der Sicherheitsabfrage geht es darum, dass die betreffende Webseite dem Passwortvergesser eine Frage präsentiert, die sie oder er beantworten soll. Nun stellt die Webseite ja schon vorher eine Frage, nämlich ‘Parole!’ (oder genauer: ‘Benutzername und das Passwort!’), die man aber nicht beantworten konnte.

Bei der Sicherheitsabfrage ist aber die Idee, dass hier eine Frage gestellt wird, die voll aus dem Leben des Passwortvergessers gegriffen ist. Also z. B. ‘Wie ist der Name Deiner Mutter?’, weitere Beispiele unten. Die Art von Frage also, die man auch dann noch beantworten kann, wenn man nach einer einhändigen Weltumsegelung nun wirklich alles andere vergessen hat.

An dieser Stelle ist es wichtig noch einmal zu betonen, welche Relevanz die Sicherheitsfrage hat: Wer sie richtig beantworten kann, kann das entsprechende Konto übernehmen und danach wird es dann richtig schwierig wieder an seine digitale Identität zu kommen. Die Wahl der Sicherheitsfrage muss also genauso ernst genommen werden wie die des Passwortes.  Und hier beginnt das Problem…

Was ist heute eigentlich noch eine gute Sicherheitsfrage, wo wir doch alles über uns bei Facebook, Twitter, Buzz und Co. bekannt geben?

Bei den Sicherheitsabfragen gibt es Internetseiten, die eine fixe Auswahl von Fragenvorschlägen anbieten, und Seiten, bei denen man eine eigene Frage formulieren kann, und Seiten mit beiden Optionen. Schwer zu beurteilen, welche Möglichkeit die bessere ist: in jedem Fall geht es ja darum eine Frage zu finden, die man selbst zwar noch beantworten kann nachdem man alles andere vergessen hat, die aber für Fremde und vielleicht auch für weniger Fremde eine harte Nuss darstellt.

Naheliegend waren daher bisher Fragen nach den privaten Verhältnissen, eben weil in der alten Zeit privat = geheim galt. Bei der Registrierung bei einem weiteren Internetdienst stand ich nun zum ersten Mal ernsthaft vor der Frage, welche der vorgegebenen Fragen wohl wirklich als Sicherheitsfrage in Frage kommen würde, gerade angesichts meiner Nutzung von verschiedenen sozialen Netzen, Blogs, etc. Ein guter Ausgangspunkt für einen Überblick, auch für einen Angreifer, ist hier mein Google Profil.

Auch wenn die dabei angestellten Überlegungen individuell sind sollen sie hier an etwas verallgemeinerten Fragestellungen nachvollzogen werden. Vielleicht überlegt die Leserin/der Leser parallel dazu, wie die Antwort aus ihrer/seiner Sicht ausfallen würde?

Fragen nach der Familie

Zu dieser Gruppe gehören Fragen wie diese:

  • Wie lautet der Mädchenname Ihrer Mutter? (Eine Frage, die auf der Annahme beruht, dass Mütter auch immer verheiratet sind und bei der Heirat ihren Namen ändern)
  • Wie lautet der zweite Vorname Ihres Vaters?
  • In welchem Jahr haben Ihre Eltern geheiratet?

Diese Art von Fragen erscheint mir in mehrfacher Hinsicht unsicher: Den Namen meiner Mutter kann man spätestens in unserem Caféblog finden, vermutlich findet sich in den dort von ihr veröffentlichten Geschichten auch ein Hinweis auf ihren Geburtsort. In diesem winzigen Ort kann man die wenigen Gehöfte an einer Hand abzählen und die Namen herausfinden. Auch der vollständige Name des Vaters sollte kein wirklich ernsthaftes Problem sein.

Das Hochzeitsdatum ist auf den ersten Blick vielleicht etwas sicherer, da wir bisher nicht auf die Idee gekommen sind irgendwelche Bilder von Familienfeiern mit Titeln wie Silberhochzeit 19XX oder so ins Netz zu stellen. Auf der anderen Seite lässt sich über mein Alter halbwegs sicher auf das Hochzeitsjahr schließen und mein Alter wiederum kann grob über die Daten zu meinem Bildungsgang (z. B. Hochschulabschluss) eruiert werden. Oder direkt aus meinem Facebook Account.

Bei allen Fragen zur Familie muss man dann auch noch berücksichtigen, dass nahe Anverwandte auch Repräsentanzen in Sozialen Netzen haben und dort vielleicht genau die Antwort auf die eigene Sicherheitsfrage ausplaudern. Daher mein Fazit: Eher keine Sicherheitsfrage mit Bezug zur Familie.

Fragen nach Haustieren

Die nächste Gruppe von Fragen ist irgendwie ähnlich zur vorherigen, nur dass sie sich nicht um menschliche Familienmitglieder drehen, sondern um tierische:

  • Wie lautet der Name ihres ersten Haustieres?
  • Wie lautet der Name Ihres Hundes/Ihrer Katze/Ihres Pferds?

Auch diese Fragenkategorie kann u. U. mit Hilfe der sozialen Netze leicht beantwortet werden. Bei mir wäre es nicht schwer herauszufinden, wie unser aktuelles Haustier heißt und welche Art von Haustier es ist. Insbesondere Fotoalben sind hier vielleicht besonders verräterisch, wenn sich irgendwo DAS TIER ins Bild schleicht und dann vielleicht sogar noch im Untertitel erwähnt wird.

Und dann habe ich noch das speziellen Problem, dass ich mich nicht mehr an meine Haustiere von gaaanz früher erinnern kann (waren einfach zu viele auf dem Bauernhof).

Fragen nach Bildungsgang oder Beruf

In diese Kategorie möchte ich Fragen der folgenden Art einsortieren:

  • Wie lautet der Name Ihrer ersten Schule?
  • Wer war in der Schule Ihr Lieblingslehrer?
  • Wie hieß Ihr erster Chef?

Die Frage nach alle Schulen, Hochschulen, KiTas und sonstigen Bildungseinrichtungen ist ja eine, die einem in Facebook gleich anspringt, und der man nur schwer ausweichen kann (sonst macht es ja keinen Spaß). Und zur Beantwortung der Frage, welche Lehrer es an welcher Schule gibt kann man Seiten nutzen a la spickmich.de. Ok, dass klappt jetzt nicht falls man die LehrerInnen meiner alten Grundschule ermitteln will, aber für die heute in Schule und Ausbildung befindliche Generation sollte man damit schon sehr weit kommen.

Auch den beruflichen Lebenslauf soll/will man natürlich möglichst umfangreich darstellen, hier nicht nur in Facebook, sondern auch im plain old Curriculum Vitae, welches natürlich im Netz steht. Die Frage nach dem ersten Chef könnte in einem Unternehmen trotzdem für Außenstehende vielleicht schwierig zu beantworten sein, falls sich auf der Firmenwebseite nicht umfangreiche Darstellungen der eigenen Führungsstrukturen im historischen Kontext finden.

In meinem Fall ist diese Frage aber sehr leicht zu beantworten, es reicht dazu das CV zu lesen.

Fragen nach Besitztümern

Zur Abrundung der kleinen Aufstellung nun noch eine vierte Sorte von Fragen und damit Schluss:

  • Von welchem Typ und welcher Farbe war Ihr erstes Auto?
  • Wie lautet Ihr erste Vielfliegernummer?
  • Welche Nummer hat Ihr Bibliotheksauswweis?

Diese Fragenkategorie hat aus meiner Sicht ein wesentliches Problem: in den meisten Fällen kann man sie nicht verwenden, weil man kein Auto besitzt, kein Vielflieger ist und seinen alten Ausweis aus der Stadtbibliothek schon vor Jahren verloren hat.

Bei der Frage nach dem ersten Auto und seiner Farbe, die ich tatsächlich in Erwägung gezogen hatte, stellte ich dann für mich zwei individuelle Probleme fest:

  1. Was ist für mich eigentlich das erste Auto? Die Familienkutsche, die man sich schon mal ausleihen durfte, oder der Kleinwagen, den man tatsächlich selbst bezahlt hatte? Und:
  2. Wie soll ich meine Antwort formulieren? ‘Opel, grün’ oder ‘Ein grüner Opel Corsa’ oder, oder…

An dieser Stelle wird ein weiteres Problem der Sicherheitsabfrage sichtbar: Wie sicher bin ich, dass ich die gleiche Frage in einigen Jahren wieder in der gleichen Weise, sowohl inhaltlich als auch in der Form, beantworten werde? Oder würde schon ein Leerzeichen mehr oder weniger reichen, damit die Webseite mit abweist?

Sicherheitsfrage: Quo vadis?

Nach den ganzen Zweifeln an der Sicherheit der Sicherheitsfragen: was ist zu tun? Letztlich hängt es wie bei allen Sicherheitsdingen stark von der eigenen Paranoia ab, insbesondere in Bezug auf das reale soziale Umfeld: will ich schon jetzt antizipieren, dass mein Freund Schlüsselvielleicht irgendwann mal mein Ex ist und mir dann möglicherweise ganz übel mitspielen will? Wie unromantisch. Oder will ich die Option eines in der netten WG Mitbewohnerin schlummernden Rachedämons berücksichtigen, der nach einmal Vergessen des Abspülens zu viel zur elektronischer Erpressung greifen würde?

Einfacher ist vermutlich ein je nach Wichtigkeit der Anwendungen unterschiedliches Vorgehen: Bei einer Internetseite, auf der es einem egal ist, kann man natürlich irgendeine Frage nehmen und sie richtig oder auch völlig beliebig beantworten.

Das Eintragen einer beliebigen (= zufälligen) Antwort kann aber auch eine Strategie für die ganz wichtigen Seiten sein: falls man sich die zufällige Antwort merkt oder besser aufschreibt und irgendwo sicher hinterlegt (am besten bei den Passworten;) hat man so einen sicheren und kaum zu knackenden Weg zur Wiederherstellung seines Kontozugangs.

Oder man merkt sich die zufällige Antwort nicht! In diesem Fall ist der Hintertür Sicherheitsfrage ein Riegel vorgeschoben und sie kann nicht mehr vom bösen Fremden genutzt werden (aber auch nicht von einem selbst). Dann muss man eben nur das Passwort aufschreiben und sicher verwahren. Und wenn das Problem des Das-Passwort-nie-mehr-verlieren gelöst ist besteht auch eigentlich gar kein Bedarf mehr an einer Sicherheitsabfrage:)

Donnerstag, 21. Januar 2010

Wie kann ich das ‘Google Handy’ Nexus One in Deutschland kaufen?

Das am 05.01.2010 heraus gekommene Nexus One Handy, schon Wochen vorher als das Google Handy im Netz gehypt, ist leider bisher direkt nur in den USA erhältlich und kann zusätzlich in einige wenige Länder (darunter England) geliefert werden. Auch wenn bereits erste Gerüchte auftauchen, dass es schon im Februar in Deutschland erhältlich sein soll, gibt es vielleicht manche, die nicht so lange warten will. Wie kann man dann vorgehen?

Ein wichtiger Hinweis vorweg

Ich übernehme keine Garantie, dass das beschriebene Verfahren funktioniert oder legal ist. Auch kann keine Verantwortung für Nebeneffekte der beschriebenen Änderungen am eigenen Computer übernommen werden. Auch über die Zuverlässigkeit der genannten Anbieter wird hier keine Aussage gemacht. Eine Nachahmung erfolgt daher immer auf eigene Gefahr.

Update: Die unten stehenden Kosten und Zeitabläufe der Bestellung sind ein eigener Erfahrungsbericht von Anfang 03/2010.  Trotzdem dürfen die beschriebenen Erfahrungen nicht verallgemeinert werden.

Hürde 1: Die Google Webseite nutzbar machen

Die Bestellung des Nexus One kann offiziell nur über diese Google Webseite erfolgen:

http://www.google.com/phone/

Leider erhält man beim Zugriff auf diese Webseite von Deutschland aus den folgenden Hinweis: "Sorry, the Nexus One phone is not available in your country."

Was nun? Im Grunde ist hier die gleiche Hürde wie bei anderen Diensten zu überwinden, die aus verschiedenen Gründen nur für US Bürger zugänglich sein sollen. Bei bekanntes Beispiel ist das Pandora Internet Radio, für das auf Grund seiner Beliebtheit spezielle Beschreibungen existieren, wie etwa hier auf netzwelt.de.

Von den dort beschriebenen drei Methoden (Proxy, TOR, Rewebber) nehme ich die Zweite, TOR. Für die Proxy Lösung müsste man sich auf die schwierige und immer wieder neue Suche nach gerade verfügbaren öffentlichen Proxyservern machen. Auch wenn es hier viele Listen gibt (z. B. hier und hier) ist dies sehr mühselig und unzuverlässig. Rewebber wie Proxify erlauben zwar einen ersten schnellen Blick auf die Nexus One Seite, wie sie sich in den USA darstellt, sind aber nicht in der Lage weitergehende Funktionen wie den notwendigen Javascript Support zu liefern.

Installation von TOR

Die TOR Installation wird in der netzwelt.de Seite recht gut beschrieben, sie ist aber nicht in allen Punkten korrekt. Der Download kann direkt von der Homepage des TOR Projektes erfolgen in Form des Vidalia-Pakets.

Nach der Installation muss man in seinem Browser (vielleicht in einem anderen als in dem, der gerade diese Instruktionen zeigt), den in TOR enthaltene Proxy (genannt Polipo) eintragen. Der hat die Adresse

127.0.0.1, Port 8118

Zwar funktioniert TOR sofort und kann als Proxy im Browser verwendet werden, allerdings ist noch nicht gewährleistet, dass das eigentliche Ziel, nämlich für die Nexus One Seite als US-amerikanischer Surfer zu erscheinen, erreicht wird: Der von TOR verwendete Endknoten kann überall in der Welt angesiedelt sein. Es ist daher noch etwas Handarbeit notwendig, und zwar durch Anpassung der Datei torrc. Wo man diese Datei findet wird in der TOR Faq beschrieben.

In dieser Datei müssen ExitNodes definiert werden, die in den USA liegen. Das grundsätzliche Format wird in der TOR Faq beschrieben, es reicht aber folgende Zeit zu ergänzen:

ExitNodes {us}

Damit haben wir unser Ziel erreicht und die erste Hürde genommen. Danach sollte der Aufruf der Nexus One Seite mit einem Browser, der den TOR Proxy verwendet, das gewünschte Ergebnis liefern:

Nexus One Seite ist verfügbar

Wichtig ist nur zu wissen, dass mit TOR im Allgemeinen, und mit dem erzwungenen Weg über einen US-Ausgangsknoten im Speziellen, die Geschwindigkeit des Internetzugriffs sehr leidet. Also Geduld bei den weiteren Schritten.

Google Checkout Account

Für den Kauf ist ein Account bei Google bzw. Google Checkout notwendig. Aber da Android sowieso nicht ohne Google Account richtig funktioniert dürfte das kein Hindernis sein:)

Tipp: Wenn man seinen Checkout Account erst noch einrichten muss, so sollte man dies aus Geschwindigkeitsgründen machen, bevor man in die TOR Verbindung wechselt (oder einen anderen Browser nutzen, der nicht über TOR läuft).

Hürde Nr 2: Eine Lieferadresse in den USA oder UK

Nun sind wir mitten im Onlineshop, haben vielleicht auch schon unsere individuelle Gravur eingegeben, und stehen plötzlich vor dem nächsten Problem: Es sind nur Lieferadressen in den USA oder UK (oder Singapur, was uns nicht weiter interessiert) möglich. Wer jetzt nicht zufällig Freunde oder Verwandte in diesen Ländern hat braucht etwas anderes: einen ‘toten’ Briefkasten in einem dieser Länder. Der ‘tote’ Briefkasten muss dann natürlich unser Paket weitersenden und vertrauenswürdig sein, damit unser schon bezahlten Nexus One nicht unterwegs verschwindet.

Und natürlich gibt es auch hier schon Dienstleister, die  so etwas übernehmen. Einer davon ist Borderlinx. Er bietet sich vielleicht deshalb an, weil er DHL verbandelt ist. Nach der Registrierung hat man auf einmal eine Adresse in den USA und in UK. Man findet auch einen praktischen Kostenrechner. Um ihn zu füttern braucht man einige Angaben:

Gewicht: Nach meinen Erfahrungen ist das Nexus One Paket ca. 1.7kg schwer
Masse:  Kann man leer lassen

Jetzt kann man die Bestellmaske ausfüllen. Das die verwendete Kreditkarte keine US-amerikanische ist stört bei der Bestellung nicht weiter. Ein alternativer Anbieter für ‘tote’ Briefkästen ist www.myus.com.

Was kostet der Spaß?

Nachdem ich Anfang März 2010 eine Bestellung nach dem oben beschriebenen Verfahren ausgeführt habe kann ich hier die in meinem Fall tatsächlich angefallenen Kosten angeben. Die Kosten teilen sich auf in die Kosten für das Handy an sich (Google) und den Versand/Import (Borderlinx). Alle Preise sind in US Dollar:

Kostenfaktor

Kosten (US Dollar)

Google:  
Nexus One Phone

529

Nexus One Docking Station

45

Shipping - FedEx overnight

0

Tax (OH)

38.74

Google gesamt

612.74

   
Borderlinx  
Tax

116.37

Duty

0

Shipping Charges

38.50

Borderlinx gesamt

154.87

   
Kosten Total

767.61

Zur Umrechnung in den aktuellen EURO Preis kann man den Yahoo Konverter nutzen. Die Dockingstation ist natürlich optional und ich frage mich, ob man die Ohio Tax nicht irgendwie zurück bekommen könnte.

Skript einer Bestellung

Der Ablauf einer Bestellung sieht so aus (ganz konkret am Beispiel einer Bestellung von Anfang März 2010):

Tag 1 (Sonntag Nacht) Bestellung auf der Google Webseite. Die Bestätigung von Checkout kommt kurze Zeit später.
Tag 2 (Montag) Der Google Shop hat das Nexus One verschickt. Die Lieferung kann über die FedEx Seite verfolgt werden.
Tag 3 (Dienstag) FedEx liefert das Paket laut Trackingcode bei Borderlinx ab.
Tag 4 (Mittwoch)

Google belastet die Kreditkarte, dass Nexus One ist damit bezahlt.

Borderlinx benachrichtigt per eMail über den Eingang und die Zuordnung der Lieferung verbunden mit einer Zahlungsaufforderung bzw. der Frage, wann verschickt werden soll.

Bezahlung Borderlinx und Beauftragung mit dem Versand (Normal, nicht Express) .

Bestätigung von Borderlinx über den Versand der Lieferung

Tag 5-8 (Montag)

In der Zeit vom Versand durch Borderlinx bis zur Ablieferung durch DHL lassen sich leider nur wenige Trackinginformationen erhalten und zwar über die Borderlinx Webseite. Meist steht dort eine Meldung, dass der kein Status zur Verfügung steht. Zwischenzeitlich gab es Anzeigen wie die, dass die Lieferung von Cincinnatti abgeschickt worden sei und am Montag dann, dass sie Leipzig verlassen habe.

Am Montag Vormittag ist das Paket dann abgekommen!

Die Frage bleibt: Soll man den Import wagen?

Nachdem das Verfahren nun erklärt ist bleibt die Frage, soll man den Import wirklich wagen? Folgende Fragen stellen sich hier:

Kann ein Import-Nexus das UTMS Netz nutzen?

Die technischen Spezifikationen geben grundsätzlich Auskunft über die Hardwareausstattung des Geräts, noch konkreter ist aber diese Seite im Help Center.

Funktioniert die Spracherkennung auch für Deutsch?

Die Spracherkennung scheint für einige Kommentatoren, wie z. B. in netzwertig.com und neuerdings.com, eine der ganz wesentlichen Innovationen des mit dem Nexus One erstmals ausgelieferten Android 2.1 Betriebssystems zu sein. Dieses Youtube Video zeigt sie sehr anschaulich und überzeugend, trotz des merkwürdigen Titels:

Wichtig wäre es daher zu wissen, ob diese Spracherkennung denn überhaupt auch für die deutsche Sprache funktioniert? Leider scheint das Help Center hier zur Zeit noch keine wirkliche Antwort zu geben.

Update: Das Anfang März 2010 bestellte Nexus One hat noch keine deutsche Spracherkennung. Allerdings wird die Sprache sofort verfügbar, sobald sie auf den Google Servern grundsätzlich angeboten wird.

Garantiefälle

Der Garantiefall ist sicher ein Argument gegen den Import. Wenn man bereit ist das Risiko einzugehen, sollte man nur vielleicht beim Auspacken etwas vorsichtiger zu Wege gehen, als in diesem Video:

Alternative Beschreibungen

Es gibt noch andere Seiten, die beschreiben, wie man das Nexus One in Deutschland erhalten kann:

Die Verfahren ähneln meiner Beschreibung, allerdings setzen beide auf die Nutzung eines Proxies. Nach dem Erfahrung über deren mangelnde Zuverlässigkeit und die potentiellen Sicherheitsprobleme (der Proxy kann schließlich die gesamte Kommunikation mitlesen) erscheint die oben beschrieben TOR Lösung aber weiterhin überlegen.

Montag, 11. Januar 2010

Heiligenhafen nach ‘Daisy’

In unserem diesjährigen Winterurlaub in Heiligenhafen erreichen uns viel mehr Anrufe von Freunden und Verwandten als in früheren Jahren. Alle sind in Sorge. Anlass sind offenbar die recht drastischen Schilderungen der Lage nach dem Durchzug von Tief ‘Daisy’ in Fehmarn und nahen Städten, die unter Stromausfällen und starken Schneeverwehungen leiden oder litten. In Heiligenhafen war es aber nach unserem Eindruck nicht wirklich dramatisch, und damit man uns glaubt hier eine kleine Bilderstrecke von gestern und heute.

Schnee, aber nicht in Massen

Am Samstag, dem 09.01.2010, ist in Heiligenhafen fast kein Schnee gefallen, am Sonntag überhaupt keiner. Erst am heutigen Montag fällt eine nennenswerte Menge (insbesondere jetzt, während dieser Text geschrieben wird).

Die 'Famila' Kreuzung in Heiligenhafen mit Schneehaufen, H. Brune Das trotzdem an einigen Stellen durchaus gewaltige Schneewehen oder geräumte –haufen entstanden sind, liegt aber daran, dass der scharfe Wind allen in den Vortagen gefallenen Schnee wieder aufgenommen, weiter transportiert und an einigen wenigen Stellen konzentriert hat. So sieht man in der Landschaft hohe Schneewehen (man beachte im folgenden Bild den Kopf des Hundes) neben komplett blanken Äckern:

Schneewehe in Heiligenhafen, H. Brune Die flachen Äcker sahen daher bei richtig gewähltem Blickwinkel heute Nachmittag so aus, als ob in den letzten Tagen und Wochen fast kein Schnee gefallen sei:

Felder bei Heiligenhafen im Winter, H. Brune Wenn man hingegen an andere Stellen geht, so finden sich richtige Schneewehen:

Zorro auf hoher Schneewehe, H. Brune Für dieses Bild stand der Fotograph aufrecht und war nicht etwa auf Knien, Zorro ist also ungefähr auf Kopfhöhe, während er den Gipfel dieser massiven Schneewehe schon überwunden hat.

Starker Wind und Hochwasser

Wirklich extrem waren für uns Binnenländer hingegen die Windverhältnisse am Samstag und Sonntag. Für die Küstenbewohner ist so ein brausender Sturm vermutlich gewohnt, für uns war er das wesentliche Erlebnis am Wochenende. Wann haben wir bei uns schon mal einen Wind, der einen vor sich herschiebt bzw. das Vorwärtskommen auf gerade Strecke ähnlich anstrengend werden lässt wie einen Aufstieg auf unseren heimischen Teutoburger Wald?

Schneetreiben in Heiligenhafen, H. Brune Ein Wind der so hart ist, dass er schon seit Tagen liegenden Schnee wieder aufnehmen und viele Kilometer mit sich führen kann und dann auch noch zwei volle Tage lang anhält? Vermutlich nur einmal in 10 Jahren.

Eine Folge dieses Windes war denn auch ein hoher Wasserstand, der im Yachthafen die Stege zum größten Teil im Wasser versinken lies:

Stege unter Wasser in Heiligenhafen, H. Brune Sonst sind diese Stege wenigstens einen halben Meter über dem Meeresspiegel. Am Strand spuckte die aufgewühlte Ostsee jede Menge Treibgut aus:

Treibgut am Strand von Heiligenhafen, H. Brune Im Hintergrund kann man die Windräder auf Fehmarn sehen. Ob diese im Sturm wegen zu viel Wind oder weil die Stromleitungen unterbrochen waren abgeschaltet werden mussten haben wir leider nicht beobachtet.

Für die Tierwelt ist das Wetter kein Problem

Die Wetterunbilden scheinen aber eher uns Menschen zu berühren, die Natur in Form ihrer Tiere und Pflanzen ist offenbar nicht weiter beeindruckt. So sind die Enten, Möwen, Gänse, Kormorane, Wasserhühner, Saatkrähen und so weiter wie immer am Hafen, am Gras- und am Steinwarder zu beobachten:

Möwen in Heiligenhafen, H. Brune

An den von Eisschollen durchsetzen Meeresrändern gründeln die Stockenten und die Möwen scheinen mit dem Wind, und sei er noch so stark, geradezu zu spielen.

Auf den kahlen, dem Wind schutzlos ausgesetzen Äckern am Steilufer sind überall Hasen zu sehen, die in kleinen Gruppen ohne Deckung zu suchen dem Sturm und dem Schnee trotzen:

Hasen in Heiligenhafen, H. BruneOffensichtlich macht den ‘Seehasen’ dieses Wetter nicht das Geringste aus. Auch die Gürtelgalloways hinter dem Ferienzentrum stehen zwar dicht zusammengedrängt um die Futterstellen, wirken aber unter ihren unglaublich dicken Pelz völlig ungerührt und beschäftigen sich wie immer im wesentlichen mit Wiederkäuen:

Gürtelgalloway in Heiligenhafen, H. Brune So lange es friert und damit ‘trocken’ bleibt, haben sie keine Probleme. Nur das Hochwasser macht ihnen vielleicht ‘Sorgen’: Es hat noch heute große Teile ihrer Salzwiesen überschwemmt, so dass die Rinder auf ihrem Futterhügel bleiben.

Für uns Urlauber ein Erlebnis

Für uns Urlauber ist dieses aufregende Wetter schön, auch wenn es den Einheimischen wohl eher lästig fällt. Auch beim Fotografieren bietet es Motivmöglichkeiten, die von der See ganz ungewohnt und neu sind. Mit einem solchen, eher abstrakten und leicht verfremdeten Motiv endet der kurze Wetterbericht aus Heiligenhafen nach ‘Daisy’:

Distel im Schnee in Heiligenhafen, H. Brune

Sonntag, 19. Juli 2009

GWT 1.6 Hosted Mode: Internen Jetty Server mit JDNI Datasourcen und Environment Informationen für PostgreSQL versorgen

DSCF0005c
Update: Auch in GWT Version 2.0.3 scheint das Verfahren weiterhin zu funktionieren!
Als eines der mühseligsten Dinge, die man beim Einstieg in die GWT Programmierung herausfinden muss, empfand ich die Lösung der folgende Frage:
Wie bringt man den internen Jetty Server, der bei der Hosted Mode Entwicklung unter Eclipse mit dem Google Plugin verwendet wird dazu, der serverseitigen Programmierung JBDC Verbindungen bzw. Connection Pools und andere JNDI Ressourcen zur Verfügung zu stellen?
Vermutlich wird fast jedes halbwegs ambitionierte GWT Projekt irgendwann vor dieser Aufgabe stehen. Falls sie nicht gelöst wird müsste man auf die enormen Vorteile der Hosted Mode Entwicklung verzichten, sein GWT Projekt für jeden Testlauf übersetzen (Java –> Javascript) und ohne die hilfreichen Entwicklungsfunktionen auskommen.

Infos im Web

In den eigentlichen GWT Seiten findet man keine besonders hilfreichen Informationen. In dem Thread Setting DataSource (JNDI) in GWT 1.6 (hosted mode – Jetty) in den Google Groups findet man allerdings Hilfestellungen, die einen letztlich zu der Lösung bringen.
Bei meinem ersten Anlauf zur Problemlösung bin ich allerdings folgendem Link aus den Kommentaren gefolgt, weil die Lösung einfacher schien:
http://humblecode.blogspot.com/2009/05/gwt-16-using-jndi-datasource.html
Auch findet man weitere hilfreiche Links, z. B. zu passenden Jetty Seiten. Leider bin ich bei dieser Lösung an der Frage gescheitert, wie man dem Jetty Server den per Default fehlenden JNDI Context java:comp/env zur Verfügung stellt. Daher habe ich dann letztlich doch die Lösung aus den Google Groups umgesetzt. Dies, und die Anpassung für unsere PostgreSQL Datenbank, soll im Folgenden beschrieben werden:

Schrittchen für Schrittchen

1. Jetty und JDBC JARs
Zunächst sollte man sich die notwendigen JARs besorgen. Dies sind zum einem Erweiterungen für Jetty, zum anderen der JDBC Treiber für PostgreSQL. Hier die Links für den Download:
Jetty: http://dist.codehaus.org/jetty/
Hier findet man Jetty bis Version 6. Ab Version 7 ist der Download beim Eclipse Projekt zu finden. Beim Download einer 6er Version in eines der Unterverzeichnisse gehen und das größere (nicht-src) ZIP Archiv holen, darin finden sich die beiden JARs.
PostgreSQL JDBC: http://jdbc.postgresql.org/download.html
Ich habe die JDBC3 Version verwendet.
Insgesamt muss man dem Jetty Server dann folgende JARs verfügbar machen:
  • jetty-naming-*.jar
  • jetty-plus-*.jar
  • postgresql-*.jdbc3.jar
Man kann die JARs der Einfachheit halber in /war/WEB-INF/lib/ platzieren, auch wenn für die eigentliche Anwendung nicht gebraucht werden.  Die JARs müssen dann in den Launch Configuration Properties in den Classpath gesetzt werden (unter User Entries).
2. jetty-env.xml
Im /war/WEB-INF/ Verzeichnis die Datei jetty-env.xml anlegen. Hier werden nun die Ressourcen für den JNDI Kontext angelegt. Leider kann man dabei nur wenig von einer eventuell vorhandenen Konfiguration für Tomcat lernen, da Jetty vieles anders macht. In unserem Fall muss neben der DataSource auch eine Konfigurationsinformation abgelegt werden. Mit beiden Definitionen sieht meine jetty-env.xml so aus:
<?xml version="1.0"?>

<!-- Wird nur fuer die Nutzung des Hosted Modes bei der GWT Entwicklung gebraucht -->

<configure class="org.mortbay.jetty.webapp.WebAppContext">

<new class="org.mortbay.jetty.plus.naming.EnvEntry">
<arg></arg>
<arg>meinEnvParameter</arg>
<arg type="java.lang.String">irgendein String</arg>
<arg type="boolean">true</arg>
</new>

<new id="jdbc/meinDBPool" class="org.mortbay.jetty.plus.naming.Resource">
<arg></arg>
<arg>jdbc/meinDBPool</arg>
<arg>
<new class="org.postgresql.ds.PGSimpleDataSource">
<set name="User">meinPostgresBenutzer</set>
<set name="Password">meinPostgresPasswort</set>
<set name="DatabaseName">meinePostgresDatenbank</set>
<set name="ServerName">localhost</set>
<set name="PortNumber">5432</set>
</new>
</arg>
</new>

</configure>


Die entsprechenden Ressourcen müssen natürlich auch wie immer in der web.xml definiert werden:


<resource-ref>
<res-ref-name>jdbc/meinDBPool</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>


Aber das sollte in den meisten Fällen schon der Fall sein.


3. env-Kontext konfigurieren


Ein Problem ist jetzt noch zu überwinden: Jetty kennt in der Standardkonfiguration noch keinen Environment Context, also das, was man typischerweise so abfragt:


Context initCtx = new InitialContext();
Context myEnv = (Context) initCtx.lookup("java:comp/env");


Möglicherweise soll Jetty auf diese Weise schlank gehalten werden für bestimmte Einsatzszenarien, aber hier stellt es noch einen weiteren Stolperstein dar, der zu überwinden ist. Es scheint möglich zu sein, Jetty über die XML Konfiguration mit dem Kontext zu versorgen, aber leider habe ich nicht herausgefunden wie. Daher wird der in den Google Groups beschriebene Weg eingeschlagen, der in der Implementierung einer eigenen Starterklasse für den internen Server besteht.


Das GWT verwendet per Default die Klasse



com.google.gwt.dev.shell.jetty.JettyLauncher



um den Server für den Hosted Mode zu starten. Diese Klasse befindet sich samt Quellcode im gwt-dev-windows.jar. Diese Klasse muss erweitert werden. Am einfachsten geht dies vermutlich in dem man sich den Quellcode in eine eigene Klasse kopiert (beim Upgrade auf das nächste GWT muss man vielleicht nachsehen, ob sich etwas verändert hat). Nennen wir die neue Klasse



org.unibi.sm.edit.MyCustomJettyLauncher



und legen sie im Sourceverzeichnis des GWT Projekts ab. Jetzt geht es nur noch darum dem WebAppClassLoader die entsprechende Konfiguration unterzuschieben, mit der er uns den gewünschten Kontext zur Verfügung stellt. Hier der entsprechende Codeschnipsel, am Ende findet sich noch einmal die komplette MyCustomJettyLaucher.java:


// Zusaetzlicher Quellcode Anfang:
private static String[] __dftConfigurationClasses = {
"org.mortbay.jetty.webapp.WebInfConfiguration", // 
"org.mortbay.jetty.plus.webapp.EnvConfiguration",// jetty-env
"org.mortbay.jetty.plus.webapp.Configuration", // web.xml
"org.mortbay.jetty.webapp.JettyWebXmlConfiguration",// jettyWeb
};
// Zusaetzlicher Quellcode Ende.

/**
* A {@link WebAppContext} tailored to GWT hosted mode. Features....
*/
protected final class WebAppContextWithReload extends WebAppContext {

/**
* Specialized {@link WebAppClassLoader} that allows outside…
*/
private class WebAppClassLoaderExtension extends WebAppClassLoader {

private static final String META_INF_SERVICES = "META-INF/services/";

public WebAppClassLoaderExtension() throws IOException {
super(bootStrapOnlyClassLoader, WebAppContextWithReload.this);

// Zusaetzlicher Quellcode Anfang:
setConfigurationClasses(__dftConfigurationClasses);
// Zusaetzlicher Quellcode Ende.
}


Es werden also im Konstruktor der inneren Klasse, die den WebAppClassLoader erweitert, eine Liste von zuvor definierten Konfigurationsklassen hinzugefügt. Als letztes muss jetzt noch die Run Configuration des Projektes dazu gebracht werden unsere neue Launcherklasse zu verwenden. Dazu wird einfach im Arguments-Reiter unter Program arguments die folgende Option ergänzt:



-server org.unibi.sm.edit.MyCustomJettyLauncher



So sieht es dann aus:


EclipseJetty


4. Start


Wenn alles richtig gemacht wurde sollte der interne Jetty jetzt ohne Fehlermeldungen starten und die serverseitige GWT Programmierung kann wie oben beschrieben auf Datenbanken und andere Environment Objekte zugreifen.


Wichtig: Um den Effekt von Änderungen zu testen sollte man eine eventuell laufende Hosted Mode Umgebung komplett stoppen und neu starten.




Der dritte Weg



Ergänzend noch der Hinweis auf einen möglichen dritten Weg zwischen Verzicht auf den Hosted Mode und der mühseligen Jetty Konfiguration: Oliver beschreibt einen Weg um den Hosted Mode ohne den eingebauten Server zu verwenden. Hier werden dann der serverseitige Code und die statische Inhalte des Projektes über einen externen AppServer ausgeführt bzw. geliefert. Das ist besonders dann interessant, wenn man sowieso einen schon fertig konfigurierten AppServer für seine Entwicklung hat. Allerdings bezieht sich Olivers Text auf eine schon etwas ältere GWT Version, bei der noch Tomcat als interner Server verwendet wurde.




Quellcode ‘org.unibi.sm.edit.MyCustomJettyLauncher’



package org.unibi.sm.edit;

import com.google.gwt.core.ext.ServletContainer;
import com.google.gwt.core.ext.ServletContainerLauncher;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.dev.shell.jetty.JettyNullLogger;
import com.google.gwt.dev.util.InstalledHelpInfo;

import org.mortbay.component.AbstractLifeCycle;
import org.mortbay.jetty.AbstractConnector;
import org.mortbay.jetty.Request;
import org.mortbay.jetty.RequestLog;
import org.mortbay.jetty.Response;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.handler.RequestLogHandler;
import org.mortbay.jetty.nio.SelectChannelConnector;
import org.mortbay.jetty.webapp.WebAppClassLoader;
import org.mortbay.jetty.webapp.WebAppContext;
import org.mortbay.log.Log;
import org.mortbay.log.Logger;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;

/**
* A {@link ServletContainerLauncher} for an embedded Jetty server.
*/
public class MyCustomJettyLauncher extends ServletContainerLauncher {

/**
* Log jetty requests/responses to TreeLogger.
*/
public static class JettyRequestLogger extends AbstractLifeCycle implements
RequestLog {

private final TreeLogger logger;

public JettyRequestLogger(TreeLogger logger) {
this.logger = logger;
}

/**
* Log an HTTP request/response to TreeLogger.
*/
@SuppressWarnings("unchecked")
public void log(Request request, Response response) {
int status = response.getStatus();
if (status < 0) {
// Copied from NCSARequestLog
status = 404;
}
TreeLogger.Type logStatus, logHeaders;
if (status >= 500) {
logStatus = TreeLogger.ERROR;
logHeaders = TreeLogger.INFO;
} else if (status >= 400) {
logStatus = TreeLogger.WARN;
logHeaders = TreeLogger.INFO;
} else {
logStatus = TreeLogger.INFO;
logHeaders = TreeLogger.DEBUG;
}
String userString = request.getRemoteUser();
if (userString == null) {
userString = "";
} else {
userString += "@";
}
String bytesString = "";
if (response.getContentCount() > 0) {
bytesString = " " + response.getContentCount() + " bytes";
}
TreeLogger branch = logger.branch(logStatus, String.valueOf(status)
+ " - " + request.getMethod() + ' ' + request.getUri()
+ " (" + userString + request.getRemoteHost() + ')'
+ bytesString);
TreeLogger headers = branch.branch(logHeaders, "Request headers");
Enumeration headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String hdr = headerNames.nextElement();
String hdrVal = request.getHeader(hdr);
headers.log(logHeaders, hdr + ": " + hdrVal);
}
// TODO(jat): add response headers
}
}

/**
* An adapter for the Jetty logging system to GWT's TreeLogger. This
* implementation class is only public to allow {@link Log} to instantiate
* it.
* 
* The weird static data / default construction setup is a game we play with
* {@link Log}'s static initializer to prevent the initial log message from
* going to stderr.
*/
public static class JettyTreeLogger implements Logger {
private final TreeLogger logger;

public JettyTreeLogger(TreeLogger logger) {
if (logger == null) {
throw new NullPointerException();
}
this.logger = logger;
}

public void debug(String msg, Object arg0, Object arg1) {
logger.log(TreeLogger.SPAM, format(msg, arg0, arg1));
}

public void debug(String msg, Throwable th) {
logger.log(TreeLogger.SPAM, msg, th);
}

public Logger getLogger(String name) {
return this;
}

public void info(String msg, Object arg0, Object arg1) {
logger.log(TreeLogger.INFO, format(msg, arg0, arg1));
}

public boolean isDebugEnabled() {
return logger.isLoggable(TreeLogger.SPAM);
}

public void setDebugEnabled(boolean enabled) {
// ignored
}

public void warn(String msg, Object arg0, Object arg1) {
logger.log(TreeLogger.WARN, format(msg, arg0, arg1));
}

public void warn(String msg, Throwable th) {
logger.log(TreeLogger.WARN, msg, th);
}

/**
* Copied from org.mortbay.log.StdErrLog.
*/
private String format(String msg, Object arg0, Object arg1) {
int i0 = msg.indexOf("{}");
int i1 = i0 < 0 ? -1 : msg.indexOf("{}", i0 + 2);

if (arg1 != null && i1 >= 0) {
msg = msg.substring(0, i1) + arg1 + msg.substring(i1 + 2);
}
if (arg0 != null && i0 >= 0) {
msg = msg.substring(0, i0) + arg0 + msg.substring(i0 + 2);
}
return msg;
}
}

/**
* The resulting {@link ServletContainer} this is launched.
*/
protected static class JettyServletContainer extends ServletContainer {
private final int actualPort;
private final File appRootDir;
private final TreeLogger logger;
private final Server server;
private final WebAppContext wac;

public JettyServletContainer(TreeLogger logger, Server server,
WebAppContext wac, int actualPort, File appRootDir) {
this.logger = logger;
this.server = server;
this.wac = wac;
this.actualPort = actualPort;
this.appRootDir = appRootDir;
}

public int getPort() {
return actualPort;
}

public void refresh() throws UnableToCompleteException {
String msg = "Reloading web app to reflect changes in "
+ appRootDir.getAbsolutePath();
TreeLogger branch = logger.branch(TreeLogger.INFO, msg);
// Temporarily log Jetty on the branch.
Log.setLog(new JettyTreeLogger(branch));
try {
wac.stop();
wac.start();
branch.log(TreeLogger.INFO, "Reload completed successfully");
} catch (Exception e) {
branch.log(TreeLogger.ERROR,
"Unable to restart embedded Jetty server", e);
throw new UnableToCompleteException();
} finally {
// Reset the top-level logger.
Log.setLog(new JettyTreeLogger(logger));
}
}

public void stop() throws UnableToCompleteException {
TreeLogger branch = logger.branch(TreeLogger.INFO,
"Stopping Jetty server");
// Temporarily log Jetty on the branch.
Log.setLog(new JettyTreeLogger(branch));
try {
server.stop();
server.setStopAtShutdown(false);
branch.log(TreeLogger.INFO, "Stopped successfully");
} catch (Exception e) {
branch.log(TreeLogger.ERROR,
"Unable to stop embedded Jetty server", e);
throw new UnableToCompleteException();
} finally {
// Reset the top-level logger.
Log.setLog(new JettyTreeLogger(logger));
}
}
}

private static String[] __dftConfigurationClasses = {
"org.mortbay.jetty.webapp.WebInfConfiguration", // 
"org.mortbay.jetty.plus.webapp.EnvConfiguration",// jetty-env
"org.mortbay.jetty.plus.webapp.Configuration", // web.xml
"org.mortbay.jetty.webapp.JettyWebXmlConfiguration",// jettyWeb
};

/**
* A {@link WebAppContext} tailored to GWT hosted mode. Features hot-reload
* with a new {@link WebAppClassLoader} to pick up disk changes. The default
* Jetty {@code WebAppContext} will create new instances of servlets, but it
* will not create a brand new {@link ClassLoader}. By creating a new
* {@code ClassLoader} each time, we re-read updated classes from disk.
* 
* Also provides special class filtering to isolate the web app from the GWT
* hosting environment.
*/
protected final class WebAppContextWithReload extends WebAppContext {

/**
* Specialized {@link WebAppClassLoader} that allows outside resources
* to be brought in dynamically from the system path. A warning is
* issued when this occurs.
*/
private class WebAppClassLoaderExtension extends WebAppClassLoader {

private static final String META_INF_SERVICES = "META-INF/services/";

public WebAppClassLoaderExtension() throws IOException {
super(bootStrapOnlyClassLoader, WebAppContextWithReload.this);

setConfigurationClasses(__dftConfigurationClasses);
}

@Override
public URL findResource(String name) {
// Specifically for
// META-INF/services/javax.xml.parsers.SAXParserFactory
String checkName = name;
if (checkName.startsWith(META_INF_SERVICES)) {
checkName = checkName.substring(META_INF_SERVICES.length());
}

// For a system path, load from the outside world.
URL found;
if (isSystemPath(checkName)) {
found = systemClassLoader.getResource(name);
if (found != null) {
return found;
}
}

// Always check this ClassLoader first.
found = super.findResource(name);
if (found != null) {
return found;
}

// See if the outside world has it.
found = systemClassLoader.getResource(name);
if (found == null) {
return null;
}

// Warn, add containing URL to our own ClassLoader, and retry
// the call.
String warnMessage = "Server resource '"
+ name
+ "' could not be found in the web app, but was found on the system classpath";
if (!addContainingClassPathEntry(warnMessage, found, name)) {
return null;
}
return super.findResource(name);
}

/**
* Override to additionally consider the most commonly available JSP
* and XML implementation as system resources. (In fact, Jasper is
* in gwt-dev via embedded Tomcat, so we always hit this case.)
*/
@Override
public boolean isSystemPath(String name) {
name = name.replace('/', '.');
return super.isSystemPath(name)
|| name.startsWith("org.apache.jasper.")
|| name.startsWith("org.apache.xerces.");
}

@Override
protected Class<?> findClass(String name)
throws ClassNotFoundException {
// For system path, always prefer the outside world.
if (isSystemPath(name)) {
try {
return systemClassLoader.loadClass(name);
} catch (ClassNotFoundException e) {
}
}

try {
return super.findClass(name);
} catch (ClassNotFoundException e) {
// Don't allow server classes to be loaded from the outside.
if (isServerPath(name)) {
throw e;
}
}

// See if the outside world has a URL for it.
String resourceName = name.replace('.', '/') + ".class";
URL found = systemClassLoader.getResource(resourceName);
if (found == null) {
return null;
}

// Warn, add containing URL to our own ClassLoader, and retry
// the call.
String warnMessage = "Server class '"
+ name
+ "' could not be found in the web app, but was found on the system classpath";
if (!addContainingClassPathEntry(warnMessage, found,
resourceName)) {
throw new ClassNotFoundException(name);
}
return super.findClass(name);
}

private boolean addContainingClassPathEntry(String warnMessage,
URL resource, String resourceName) {
TreeLogger.Type logLevel = (System
.getProperty(PROPERTY_NOWARN_WEBAPP_CLASSPATH) == null) ? TreeLogger.WARN
: TreeLogger.DEBUG;
TreeLogger branch = logger.branch(logLevel, warnMessage);
String classPathURL;
String foundStr = resource.toExternalForm();
if (resource.getProtocol().equals("file")) {
assert foundStr.endsWith(resourceName);
classPathURL = foundStr.substring(0, foundStr.length()
- resourceName.length());
} else if (resource.getProtocol().equals("jar")) {
assert foundStr.startsWith("jar:");
assert foundStr.endsWith("!/" + resourceName);
classPathURL = foundStr.substring(4, foundStr.length()
- (2 + resourceName.length()));
} else {
branch.log(TreeLogger.ERROR,
"Found resouce but unrecognized URL format: '"
+ foundStr + '\'');
return false;
}
branch = branch.branch(logLevel, "Adding classpath entry '"
+ classPathURL
+ "' to the web app classpath for this session", null,
new InstalledHelpInfo("webAppClassPath.html"));
try {
addClassPath(classPathURL);
return true;
} catch (IOException e) {
branch.log(TreeLogger.ERROR, "Failed add container URL: '"
+ classPathURL + '\'', e);
return false;
}
}
}

/**
* Parent ClassLoader for the Jetty web app, which can only load JVM
* classes. We would just use null for the parent
* ClassLoader except this makes Jetty unhappy.
*/
private final ClassLoader bootStrapOnlyClassLoader = new ClassLoader(
null) {
};

private final TreeLogger logger;

/**
* In the usual case of launching {@link com.google.gwt.dev.HostedMode},
* this will always by the system app ClassLoader.
*/
private final ClassLoader systemClassLoader = Thread.currentThread()
.getContextClassLoader();

@SuppressWarnings("unchecked")
private WebAppContextWithReload(TreeLogger logger, String webApp,
String contextPath) {
super(webApp, contextPath);
this.logger = logger;

// Prevent file locking on Windows; pick up file changes.
getInitParams().put(
"org.mortbay.jetty.servlet.Default.useFileMappedBuffer",
"false");

// Since the parent class loader is bootstrap-only, prefer it first.
setParentLoaderPriority(true);
}

@Override
protected void doStart() throws Exception {
setClassLoader(new WebAppClassLoaderExtension());
super.doStart();
}

@Override
protected void doStop() throws Exception {
super.doStop();
setClassLoader(null);
}
}

/**
* System property to suppress warnings about loading web app classes from
* the system classpath.
*/
private static final String PROPERTY_NOWARN_WEBAPP_CLASSPATH = "gwt.nowarn.webapp.classpath";

static {
// Suppress spammy Jetty log initialization.
System.setProperty("org.mortbay.log.class", JettyNullLogger.class
.getName());
Log.getLog();

/*
* Make JDT the default Ant compiler so that JSP compilation just works
* out-of-the-box. If we don't set this, it's very, very difficult to
* make JSP compilation work.
*/
String antJavaC = System.getProperty("build.compiler",
"org.eclipse.jdt.core.JDTCompilerAdapter");
System.setProperty("build.compiler", antJavaC);
}

public ServletContainer start(TreeLogger logger, int port, File appRootDir)
throws Exception {
TreeLogger branch = logger.branch(TreeLogger.INFO,
"Starting Jetty on port " + port, null);

checkStartParams(branch, port, appRootDir);

// Setup our branch logger during startup.
Log.setLog(new JettyTreeLogger(branch));

// Turn off XML validation.
System.setProperty("org.mortbay.xml.XmlParser.Validating", "false");

AbstractConnector connector = getConnector();
connector.setPort(port);

// Don't share ports with an existing process.
connector.setReuseAddress(false);

// Linux keeps the port blocked after shutdown if we don't disable this.
connector.setSoLingerTime(0);

Server server = new Server();
server.addConnector(connector);

// Create a new web app in the war directory.
WebAppContext wac = new WebAppContextWithReload(logger, appRootDir
.getAbsolutePath(), "/");

RequestLogHandler logHandler = new RequestLogHandler();
logHandler.setRequestLog(new JettyRequestLogger(logger));
logHandler.setHandler(wac);
server.setHandler(logHandler);
server.start();
server.setStopAtShutdown(true);

// Now that we're started, log to the top level logger.
Log.setLog(new JettyTreeLogger(logger));

return new JettyServletContainer(logger, server, wac, connector
.getLocalPort(), appRootDir);
}

protected AbstractConnector getConnector() {
return new SelectChannelConnector();
}

private void checkStartParams(TreeLogger logger, int port, File appRootDir) {
if (logger == null) {
throw new NullPointerException("logger cannot be null");
}

if (port < 0 || port > 65535) {
throw new IllegalArgumentException(
"port must be either 0 (for auto) or less than 65536");
}

if (appRootDir == null) {
throw new NullPointerException("app root direcotry cannot be null");
}
}

}