Archiv der Kategorie Technik

Hudson-Konfiguration im SVN

Keeping your configuration and data in Subversion

Auch die Konfiguration des Build-Servers selber sollte man sichern.

Howto: Ein firmeneigenes Java-Maven-Repository aufsetzen

Für diesen Artikel setze ich jetzt einfach mal voraus, dass die Begriffe und Technologien hinter Java, Maven, Repository, Eclipse und Tomcat bekannt und geläufig sind. Und nein, jeweiliger Profi muss man zum Verständnis nicht sein.

Was wollen wir?

An ein firmeneigenes Repository — oder auch: corporate repository — gelten besondere Anforderungen. Diese können bei einem “einfach privat-eigenen” verändert werden, aber man kommt meistens auf folgende Punkte:

  1. Ein Repository soll den Entwicklern zum Deployen der eigenen Artifakte und Module zur Verfügung gestellt werden. Wahlweise übernimmt dies auch ein automatischer Build-Agent wie Hudson, TeamCity und haste-nicht-gesehen.
  2. Ein Repositorymanager soll als proxy fungieren. In einer Firma spart dies nicht nur einfache Bandbreite. Da ein solcher Manager in der Regel im lokalen Netz steht, sind die Interaktionszeiten um ein Vielfaches besser.
  3. Ein so genanntes third party pepository für die Abhängigkeiten, die unbedingt notwendig sind und wovon es keine Maven-Abhängigkeiten gibt.

Für Punkt zwei spricht auch eine wesentlich einfachere Konfiguration der Clients (Entwicklerprofile), da nur noch ein Repository eingetragen werden muss. Alle “bekannten” Repositories werden zentral gebündelt, damit schwindet natürlich gleichzeitig die “Freiheit” des einzelnen Entwicklers, andere “unbekannte” Repositories zu verwenden. Dies ist jedoch vernachlässigbar, weil: Diese “Freiheit” schränkt im Endeffekt den Buildprozess und auch die Wiederverwendbarkeit ein. Das Hinzufügen von weiteren Repositories in die POM ist aus Gründen der Versionisierung und Nachhaltigkeit auch keine optimale Lösung. Dennoch, alles nur eine Sache der Konfigurations der Clients.

Was brauchen wir?

Es gibt eine Reihe von Repository-Managern, die allesamt viel können. Die Wahl auf Nexus fällt hier aus folgenden Gründen:

  • der Footprint ist mit 30 Megabyte wesentlich kleiner als bspw. Artifactory
  • die interne Verzeichnisstruktur entspricht mehr oder weniger 1:1 der realen Organisationsstruktur eines Maven-Repositorys (im Vergleich: Artifactory speichert ein eigenes Datenbankstruktur ähnliches Layout)
  • Nexus und das Eclipse-Plugin m2eclipse sind vom gleichen Hersteller Sonatype und ergänzen sich; nach dem Umstellen bemerkt der Entwickler keinen Unterschied in der Suche, Auto-Discovery, o.ä.

Eine umfangreiche Online-Dokumentation ist auf der Nexus-Seite zu finden.

Installation

Nexus wird unter anderem als WAR ausgeliefert, insofern die Installation in einen Tomcat ein leichtes ist. Beachtenswert ist dabei nur, dass Nexus ein Verzeichnis ~/sonatype-work erstellt. Da sich dort unter Umständen viele Nutzdaten ansammeln, kann ein Verschieben (symbolischer Link?) nicht verkehrt sein. Da sich mit der Laufe der Zeit einiges an Daten ansammeln kann, sollte der Platz nicht zu sparsam vermessen sein.

Umfang

Nachdem Tomcat bzw. Nexus gestartet ist, kann man sich mit dem Default-Daten admin/admin123 anmelden (analog  mit den Daten der anderen beiden Benutzern!).

Nexus kommt bereits mit einer Reihen von vorkonfigurierten, eigenen hosted repositories einher.

  • releases sammelt alle Release-Artifakte der Firma
  • snapshots sammelt alle Snapshot-Artifakte der Firma
  • third-party sammelt alle Release-Artifakte externer Quellen, wofür es keine Maven-Repositories gibt (oder wo man jenes Repository nicht generell zur Verfügung stellen will), gutes Beispiel ist ein (aktueller) Oracle-JDBC-Treiber

Daneben gibt es so genannte proxy repositories, die praktisch gesehen nur aus einem Index bestehen. Wie ein Proxy hängen sie sich zwischen dem Client und dem tatsächlichen Repository und cachen alle Artifakte lokal. Selbst der Index ist mehrere Megabytes groß, das sollte man nicht vernachlässigen. Voreingetragene proxy repositories sind Apache Snapshots, Codehaus Snapshots, Central Maven Repository (Maven1/Maven2-Repository-Konverter sind in Nexus vorhanden a.k.a. virtual repositories).

Die grouped repositories sind auch rein virtuelle Gruppierungen von verschiedenen Repositories. Das Standard Repository “Public” ist in der einfachsten Konfiguration eine Sammlung aller (aktivierten) Repositories auf dem Manager — also sowohl der externen Spiegel, der Third-Parties als auch den eigenen Artifakten.

Konfiguration

Die Aktivierung und Verwaltung von (neuen) Repositories ist abhängig der eigenen Bedürfnisse. Meistens sinnvoll ist es jedoch, bei den drei großen Spiegeln (proxy repositories) in dem Konfigurationstab das Indizieren (Download Remote Indexes) zu aktivieren. Je nach Belieben kann man in der Gruppe Administration auch das Aktualisierungsverhalten steuern.

Konfiguration: Deployment

Um ein Deployment zu gewährleisten, muss man nebst Kenntnis der Repository-URL (eben die URL) nur wissen, ob der anonyme Zugriff erlaubt sein soll, oder ob man einen Deployment-Benutzer einrichten und nutzen willst. Falls eine Richtlinie vorschreiben sollte, dass dies nur ein Build-Agent machen darf, ist ein (geheimes) Passwort oder Schlüssel unabdingbar.

Konfiguration: Client

Nehmen wir an, der Nexus-Manager ist auf dem Host 192.168.0.10:8080/nexus installiert. In der einfachen Installation und Konfiguration sammeln sich im public repository praktisch alle relevanten Artifakte (sowohl Releases als auch Snapshots).

<settings>
<mirrors>
<mirror>
<id>corporate</id>
<name>Corporate Repository</name>
<url>http://192.168.0.10:8080/nexus/content/groups/public</url>
<mirrorOf>*</mirrorOf>
</mirror>
</mirrors>
</settings>

Der Deployment-User benötigt ggf. Zugangsdaten für das entsprechende Repository.

Ein Client wie m2eclipse sollte danach einen kompletten Rebuild des Index machen.

Eclipse 3.6: Ersteindruck

Der dritte Release Candidate von Eclipse 3.6 alias Helios wurde vor wenigen Tagen bereitgestellt – man kann wohl davon ausgehen, das dem baldigen Release Juni/Juli nicht mehr viel im Weg steht.

Damit reiht sich nun ein weiterer Jupitermond in die Reihe der 3.x-Releases ein: besser, umfangreicher, aktueller.

Auf dem ersten Blick sieht Eclipse wie immer aus. Zwar wurde der Welcome-Screen, wie immer, in Punkto Design und Content geändert.. aber ansonsten ist alles wie gehabt.

Zwecks des kleinen Reviews habe ich die 64-Bit-Version (Cocoa) für Mac OS X heruntergeladen; da ich aber auch noch eine Reihe von Plugins benötige, diese dann später nachinstalliert. Prinzipiell hat sich der Updatemanager zumindestens optisch nicht zum Vorgänger geändert. Immerhin: Mit schätzungsweise 50 Einzelplugins ist der Installationsvorgang erstmalig in meiner persönlichen Eclipse-Geschichte problemlos von statten gegangen – sonst hat es immer irgendwo ein bisschen geknallt. Manchmal mit, meist ohne Auswirkungen. Unter anderem war auch ein SVN Connector Plugin dabei.

Es sieht so aus, als wäre in Eclipse kein VCS-Plugin (mehr) enthalten, vielmehr wird dies durch den Connector (ggf. bekannt aus 3.5) bekannt. Nach dem obligatorischen Neustart wird man sofort vom Connector-Wizard begrüßt und kann zwischen verschiedenen HavaHL und SVNKit-Versionen wählen. Ausgewählt, installiert, neugestartet. Fertig. Import, From SVN.. und voilá. Projekt ist drin. Interessant: Neuerdings wird man informiert, dass man gespeicherte Passwörter (SVN-Dialog) mittels Passphrasen absichern kann.

Die kleinen Details

"Eigenschaften" in Galileo

"Eigenschaften" in Helios

Ich habe mich im Vorfeld noch nicht mit den Änderungen und Neuerungen von Helios auseinandergesetzt, daher stochere ich etwas herum. Augenfällige Änderung: Die Eigenschaftsfenster einer Dateiressource wurden um eine detaillierte Rechte-Verwaltung erweitert.

Resources / Syncing

Aha… Resources können jetzt endlich gefiltert in einem Projekt eingefügt werden. Soll heißen: Man kann nicht nur weitere Resourcen dazu linken sondern auch explizit welche ausschließen. Yes!

Der Produktiveinsatz in den nächsten Wochen wird zeigen, was es sonst noch gibt.

Java Reflection API – mit Cache, ey!

Einführung in Reflection

Die Java Reflection API ist Bestandteil des JDK und ermöglicht den Zugriff auf Methoden, Felder und Annotationen von Klassen und Objekte, also den Instanzen von Klassen. Mit Ausnahme von Annotationen geschieht der Zugriff immer auf einer Meta-Ebene.

Mit einem einfachen Beispiel ist diese Meta-Ebene erklärt.

class Foo {
private String bar = "private value";
}

Stellen wir uns vor, wir wollen ganz exemplarisch von dem Objekt foo (foo = new Foo())den Inhalt von dem Feld bar erhalten. Auf dem üblichen Weg ist das nicht möglich, da das Feld ein privates ist.

Über den zugehörigen Klassentyp (via getClass()) stellt Java eine Reihe von Methoden aus dem Reflection-Paket zur Verfügung, u.a. auch Field getDeclaredField(String). Ein declared field ist ein Instanzattribut eines Objektes, während ein field (Field getField(String)) statische Felder finden.

Field field = foo.getClass().getDeclaredField('bar');

Die Variable field enthält aber – wie man dem Typ entnehmen kann – aber nicht den Inhalt von bar, sondern ein Field-Objekt. Um an den Inhalt zu kommen, verwendet man die Methode get(Object). Der Parameter bezeichnet den entsprechenden Kontext, also das Objekt foo von weiter oben.

Object value = field.get(foo);

Das bedeutet im Klartext: Auch für eine weitere Instanz der Klasse Foo (etwa foo2) kann dieses Field für dieses Feld verwendet werden. Es beinhaltet nur die Metainformationen, nicht die eigentlichen Inhalte.

Dabei ist jedoch zu beachten, dass der SecurityManager aktiv werden kann; in diesem Falle wird eine Exception bei get(Object) geschmissen, weil das Feld nicht sichtbar ist.

field.setAccessible(true);

schafft dabei Abhilfe.

Und Methoden?

Im Prinzip funktioniert das Schema bei Methoden genauso – aber bevor ich jetzt einen Radio Eriwan-Witz loslasse…

Im Gegensatz zu den vorherigen Feldern werden Methoden nicht nur über den Namen, sondern auch über die Parametertypen identifiziert (daher können Methoden sich vom Namen her in Java auch “überladen”).

class Bar {
private String name;
String getName() {
return name;
}
String getName(String defaultName) {
return (name == null) ? defaultName : name;
}
}

Die Metainformationen werden entsprechenderweise geladen:

Method method1 = bar.getClass().getDeclaredMethod("getName");
Method method2 = bar.getClass().getDeclaredMethod("getName", String.class);

Selbstverständlich ist bei Kenntnisnahme der Klasse auch folgende Zeile gleichwertend:

Method method1 = Bar.class.getDeclaredMethod("getName");

Methoden haben im Gegensatz zu Feldern keinen “Inhalt”, sondern sind eine Aktivität oder Operation — und zwar auf einem Objekt. Dementsprechend funktioniert das Ausführen mittels der Method Object invoke(Object, Object…args):

Object result1 = method1.invoke(bar); // getName()
Object result2 = method2.invoke(bar, "default name"); // getName("defaultName")

Und Annotationen?

Annotationen sind “Anmerkungen” im Quellcode, und seit Java 5 fester Bestandteil des JDKs. Technisch gesehen sind Annotationen besondere Klassen mit eingeschränkten (Java-) Möglichkeiten, deren Instanz auf einem Meta-Attribut wie Klasse, Feld, Methode oder Methodenparameter “hängen”. Mit anderen Worten bedeutet dass, dass man mittels Reflection tatsächlich eine Instanz einer Annotation erhält — allerdings mittels einem Proxy (aus der Java API).

@Entity
class Account {
@Column(name="id_x")
private Long id;
}

Die Methode getAnnotation(Class) existiert in allen Typen: Class, Field und Method.

Account account = new Account();
Entity annotation1 = Account.class.getAnnotation(Entity.class).annotationType();
Column annotation2 = Account.class.getDeclaredField("id").getAnnotation(Column.class).annotationType();
Assert.assertEquals("id_x", annotation2.name());

Performance

Im Regelfall benötigt man keinen Zugriff auf Reflection und sollte es vermeiden. Nichtsdestotrotz gestalten sich Konfigurationen, welche auf Basis von Annotationen, meist als sehr einfach, simpel und vor allem Code-konzentriert. Das JPA-Mapping (etwa mit Hilfe von Hibernate) gestaltet sich via Annotationen wesentlich einfacher, schneller und schlanker als mit XML.

Jeder Zugriff über die Reflection API kostet Zeit. Für Konfigurationen und Pläne ist das meist nebensächlich; die JPA-Konfiguration wird beim Start der Applikation eingelesen, analysiert und gespeichert. Nebenbei profitiert das natürlich von der anfänglichen “Warmup-Phase”.

Besteht jedoch ein Access on Demand, so sollte man sich Gedanken um eine geeignete Cachestruktur machen. Wichtig ist dabei, die Metadaten von den eigentlichen Inhalten zu trennen.

Cachen & Lösungsansätze

Jeder der oben genannten Reflection-Getter gibt es auch jeweils eine getAll-Variante: Class.getDeclaredFields(),Class.getDeclaredMethods(), Class.getAnnotations(), Field.getAnnotations() und Method.getAnnotations().

Mit einem einfachen Algorithmus kann man die Laufzeit drastisch senken, wenn Objekte des gleichen Typs mittels Reflection untersucht werden.

public class CacheReflectionUtil {
// cache of declared fields of class types
private final Map<Class<?>, Field[]> classDeclaredFields = new HashMap<>();
// Return the declared fields of the given class type.
public Field[] getDeclaredFields(Class<?> type) {
Field[] fields = classDeclaredFields.get(type);
if (fields == null) {
fields = type.getDeclaredFields();
classDeclaredFields.put(type, fields);
ensureAccessibility(fields);
}
return fields;
}
// Ensure that the given fields are accessible.
public void ensureAccessibility(Field[] fields) {
for (Field field : fields) {
// setAccessible will not only set a property but invoke SecurityManager stuff
if (field.isAccessible()) {
field.setAccessible(true);
}
}
}
// Return the declared field of the given class type.
public Field getDeclaredField(Class<?> type, String name) {
for (Field field : getDeclaredFields(type)) {
if (field.getName().equals(name)) {
return field;
}
}
return null;
}
}

Um einen stetigen Speicherverbrauch zu verhindern, empfiehlt sich das Nutzen einer Least-Recently-Used-Struktur. Das Apache-Commons-Paket bietet dies etwa mit der LRUMap an.

Context Affair

Bei Spring ist die globale Einheit in der Konfiguration der so genannte ApplicationContext. Dieser Context ist etwa ein Container im Applicationserver (beispielsweise web.xml). Soweit so gut.

Tatsächlich ist der WebApplicationContext eine Spezialisierung des oben genannten ApplicationContext — und zuständig für Webanwendungen. Da ein Servlet die Steuerung im Applicationserver übernimmt, benötigt der Spring-Context ein DispatcherServlet. Damit ist die “Verbindung” User->Server->Spring geschaffen. Soweit so gut.

Konfiguriert man das DispatcherServlet etwa – sinnigerweise – mit dem Namen”dispatcher”, dann sucht Spring standardgemäß nach einer dispatcher-servlet.xml. Diese XML-Konfigurationsdatei kann ähnlich der applicationContext.xml (u.ä.) ganz normale Bean-Konfigurationen enthalten. Interessant ist dabei, dass dabei ein zusätzlicher ServletContext erstellt wird. Das hat zwei Auswirkungen:

  1. Beans aus dem ServletContext sind nicht im ApplicationContext verfügbar
  2. Annotations-gestützte Konfigurationen müssen jeweilse in beiden Contexten konfiguriert, also aktiviert, werden

iPhone Webapps – Autokorrektur komplett deaktivieren

Für Webapps, also HTML-Seiten, gibt in speziellen Sitationen wie Loginformulare Problemen mit der Autovervollständigung bzw. -korrektur des iPhone OS.

Für input-Tags gibt es neben dem Attribut autocomplete=”off” (unterstützt bspw. durch den Firefox) noch zwei weitere Attribute:

  • autocorrect=”off” – die Autokorrektur abschalten
  • autocapitalize=”off” — die Auto-Groß/Kleinschreibung-Korrektur abschalten

Alle drei Attribute zusammen schalten auf iPhone/iPad/iPad sämtliche Korrekturvorschläge ab.

Featurities meets Fallstrick: Die Spring Security 3.0 Konfigurationsodyssey

Mit dem Majorrelease 3.0 wurde dem Modul Spring Security eine Menge von neuen Features angeignet. Spring Security ist die Modulkomposition, welches für das Java Framework Spring quasi die gesamte Authentifizierung, Autorisierung, Legitimierung jedwegiger Art ermöglicht.

Leider wurden mit dem Release 2.x auf 3.0 eine Reihe von API-Changes vollzogen. Zugegeben, die waren auch sicher alle sinnvoll, weil Komponenten wie die Authentifizierung weiter geteilt wurden und man somit wesentlich flexibler ist, neue Anforderungen zu ermöglichen (Baukastenprinzip). Aber die Dokumentation ist – gesamtheitlich betrachtet – irgendwie immer noch mies und oft nicht aktualisiert. Oder man findet im Internet einfach nur (alte) Beispiele.

Die http-Direktive

Im Namespace von Spring Security existiert das Tagelement http, mit welchem man kurze, knappe und verständliche Konfigurationen anlegen kann. Der Vorteil liegt klar auf der Hand: Man muss nicht alle Beans, Listener und Provider anlegen, denn das geschieht automatisch. Tja, wären da nicht ein paar Einschränkungen in der Funktionsvielfalt.

Konkretes Beispiel: Remember Me

Just wurde das Minor-Release 3.0.1 veröffentlicht, und nur wenige Tage später zu erfahren, dass Remember Me kaputt sei. Egal, fahren wir erstmal weiter mit 3.0.0.

Laut Dokumentation ist es am einfachsten, wenn man die Direktive remember-me (Security Namespace) innerhalb der http-Direktive (Security Namespace) verwendet. Ohne irgendeine Angabe wird ein stinknormales, Cookie basiertes Tokenverfahren ohne (echten) privaten Schlüssel verwendet. Reicht für den ersten Einsatz erstmal auf, soll ja erstmal funktionieren.

Fehlermöglichkeit 1a: Man loggt sich ein, und es passiert nichts (kein “RememberMe”-Cookie).
Lösung: Wenn man einen eigenen Auth-Filter einsetzt, muss man diesem auch den RememberMe-Service “setten”. Außerdem muss der SecurityChainFilter (web.xml!) auch auf die login-Seite verweisen. Es dürfen auch keine Filter bei der Konfigurierung von intercepted Urls (speziell hier: login, logout) gemacht werden.

Fehlermöglichkeit 1b: Es passiert noch immer nichts?
Lösung: Vielleicht wurde vergessen, einen Parameternamen für den Request zu setzen. Der Standardname ist ein typischer Springname, der natürlich unschön ist. Und den kann man nicht über die RememberMe-Direktive setzen, also muss man eh einen eigenen Service definieren. Bäm. Referenzierung geht dann zwar noch, aber für mehr ist die RememberMe-Direktive dann nicht mehr zu gebrauchen.

Fehlermöglichkeit 2a: Man besucht die Seite ohne Login, aber mit Cookie – und die Loginseite kommt (Log sagt kein gültiger Auth).
Lösung: Man kann der Log trauen, wenn sie zwar beim Einloggen nun einen Token ablegt (kann man zum Beispiel sehr einfach mit diesem Firefox-Addon inkl. Editor(!) verifizieren), dieses aber beim erneuten Besuchen der Seite (bzw. ohne JSPSESSION-Cookie) nicht verwendet bzw. wird nicht erkannt. Schlussendlich half u.a. das Umbenennen der Userservices-Bean in “userService”. Außerdem sollte die Loginseite keinen Filter/Access haben (s.o.) Lieber 2x prüfen!

Fehlermöglichkeit 2b: Es erscheint eine Ausnahme, dass der Key falsch sei.
Lösung: Dazu muss man wissen: Sobald  man eine individualisierte RememberMe-Konfiguration nutzt, wird auch der Key nicht mehr vernünftig auf alle Komponenten (Provider, Filter, Manager) gesetzt. Beim Anlegen wird also der eigene Key verwendet, beim Auslesen der Standardkey. Yes! (s.o.)

Fehlermöglichkeit 3: Man besucht die Seite ohne Login, aber mit Cookie – aber wie in 2 nur die Loginseite.
Lösung: Im Logger/Debugger kann man nun feststellen, dass zwar das Cookie gefunden wurde, das Token gefunden und validiert wurde aber dann keine Rechte existieren – aha? Wahrscheinlich fehlt im Provider noch ein zusätzliches Setting der Komponenten. Am besten von RememberMe Service/Filter/Provider jeweils alle möglichen Properties durchgehen. Jaja, wie gesagt.. ;)

Fehlermöglichkeit 4: Das Ausloggen (beispielsweise logout.html) hat nach Aktivierung von Rememberme plötzlich keine Auswirkungen mehr.
Lösung: Zwar wird die Seite gefunden, aber es wird kein “Logout” gemacht. Auch hier sollte man prüfen, ob ein SecurityChainFilter (web.xml) auch für die logout-Seite greift.

Fehlermöglichkeit 5: Das Besuchen der Seite wirft einen Fehler (ggf. “mit weißer Seite”), dass keine neue Session erstellt werden kann.
Lösung: Richtig, nach einem Request ist ja dann auch zu spät. Das Attribut create-session in der Direktive http sollte daher auf “ifRequeried” gestellt sein.

Fazit:

  • SecurityChainFilter immer prüfen
  • Intercepted Urls prüfen
  • RememberMe-Direktive innerhalb der http-Direktive ist quasi abgesehen von der services-ref unbrauchbar.

Anmerkung:

Natürlich kann man sich das Problem mit den SecurityChains vom Hals schaffen, indem man stupide ein /* filtert. Das hat jedoch zur Auswirkung, das Spring Security auch jeden verdammten Request anguckt; bei zusätzlichen (statischen) Inhalten wie Javascript, Stylesheets, Bildern, Flash u.ä. ist das ein Overhead, der unnötig ist.

Tags: , , ,

HTML5 & Forms

Als Ergänzung zu meinem XForms-Vortrag in der FH, hier ein paar nette Details zu den Neuerungen von HTML5/Forms. Jaja, was für eine Überaschung. Okay, nach dem Tod von XHTML2 (und demnach die Integration von XForms in XHTML) auch wieder nicht…

Ganz allgemein scheint Dive Into HTML5 aber auch empfehlenswert zu sein, wenn auch noch in Arbeit. Nett gemacht.

Tomcat Webapp Deployment/Build

Im Zuge eins kommenden Artikels/Howto über Webapp Deployment/Build suche ich noch bestehende Lösungen, gerne auch Scripts a la Ant. Auf letzterem basiert auch meine bisherige Vorgehensweise..

Update: Inkl. dem Buildprozess.

Google

Google hat also nebst so Allerweltssachen wie Mails, Cloud, Docs und Search also auch

  • ein paar Javascript Tools
  • verlinken als CDN die bekanntesten JS-Frameworks, gleichzeitig Anbieter von entsprechenden APIs für Maps, Analytics & Co.
  • Google Wave, “was vollkommen neues”, was irgendwie noch keiner (nicht viele) richtig einzurordnen / anzuwenden kann
  • ein eigenes Dateisystem (hm, man sieht noch nicht viel davon)
  • ein eigenes Betriebssystem (soll ja kommen, man hört nichts mehr)
  • ein eigenen Browser mitsamt Javascriptengine
  • just eine Internet-Protokollerweiterung/ersetzung namens SPDY von/für HTTP – mitsamt Spezifikationen, also nichts halbgares
  • “nur ein paar” technische Paper, etwa zu Map/Reduce oder BigTable
  • nebst den nicht zählbaren Rechenzentren (geschweige Containern, ganz zu schweigen Rechnern) auch noch eigene Datenleitungen…

Und die Leute haben da noch Angst vor der Datenkrake – da bahnt sich doch ein ganz anderes – liebes? – Monster an.

Und Hinweise, Links? Google! Ha!

Page optimized by WP Minify WordPress Plugin