In der aktuellen Computerbild gibt es ein “Blitzstartsystem”, welche “Chromium” enthält. Was sehr verwunderlich ist, da Google das ganze selbst noch nicht als stabil oder fertig deklariert.
Aber ein Grund das ganz mal selbst auszuprobieren!
Hat man ein Netbook, hat man das Problem, dass die CD einem gar nichts nützt, braucht man auch nicht. Alles was man zum Testen braucht ist ein USB-Stick mit mindestens 4 GB.
Mein Testsystem ist ein Samsung NC 10 Plus. Fertige Builds gibts bei http://chromeos.hexxeh.net/. Dann folgt man einfach der Anleitung auf seiner Seite.Leider scheint die Downloadrate auf 40KB/s gedrosselt, was für die 250 MB schon eine etwas längere Wartezeit benötigt. Hat man den Download gemeistert, ist man schon fast fertig, entpacken und auf den USB-Stick schreiben. Nun kann man das Netbook neu starten. Im Bios den USB-Stick als 1. Bootlaufwerk auswählen sollte man auch nicht vergessen.
Es kann an dem billigen USB-Stick liegen oder daran, dass ich ein “Debug Build” erwischt habe, die “unter 10 Sekunden” erreiche ich nicht, es sind eher 20 Sekunden, aber weit besser als das vorinstallierte Windows 7. Im Gegensatz zu vielen im Netz wurde unser W-Lan problemlos erkannt. Anmeldung (über Google Konto) und Browsen war problemlos möglich. Die Einrichtung klappte in unter 3 Minuten. Da kamen aber auch schon die ersten kleinen Fehlerteufel. Keiner davon war gravierend, aber sehr unschön:
Eine kleine Auswahl:
Sieht man aber von diesen Makeln ab, so macht das System einen sehr flotten und stabilen Eindruck.
Mein Netbook ist nun problemlos zu einem Chromebook geworden, Chromium OS hat noch einige kleinen Macken, die aber nicht groß stören. Spätestens wenn Google selbst von einer stabilen Version spricht, ist es eine Alternative für Netbook- Besitzer, welche eigentlich nur schnell mal ins Internet wollen.
Natürlich gibt es auch anderen Änderungen, wie die Aktualisierung der CellTable oder der Integrierte GWTDesigner,
eine Übersicht dazu gibt es hier. Doch die neuen HTML5 Features, mit denen ja einige Firmen wie zB Facebook schon Arbeiten,
sollen heute das Thema sein.
GWT ist ein Framework, welches die unterschiedlichen Javascript- Implementierungen der Browser weitgehend vom Entwickler fernhält.
Doch beim Thema HTML5 und vor allem Canvas gibt es nicht nur unterschiedliche Implementierungen, es kann auch gar nicht vorhanden sein.
Um welchen speziellen Browser es sich handelt, muss man wohl kaum erwähnen, in der neunten Version sollen aber die Features dabei sein.
Wenn es doch schon so weit wäre.
Auch Google hilft einem Webentwickler, welcher die Existenz des bösen Browsers vergessen hat mit ungewohnten Konstruktoren.
canvas = Canvas.createIfSupported(); audio = Audio.createIfSupported();
In Java ist die Entwicklung kaum anders als mit Javascript.
public void draw(Canvas toDraw) { Context2d context = toDraw.getContext2d(); context.clearRect(x, y, 72, 72); String toPrint = image[type][index % image[type].length]; Image map = new Image(IMAGEPATH + toPrint); context.drawImage(ImageElement.as(map.getElement()), x, y); index++; } audio.getAudioElement().setSrc("audio/elf/attack.ogg"); audio.getAudioElement().setAutoplay(true);
Interessanterweise halte ich Apple’ s iPhone für einen Meilenstein der Webentwicklung mit HTML5. Die Entscheidung kein Flash zuzulassen, nebenbei auch kein Siverlight,
hat viele Entwickler vor ein Problem gestellt: Wie kriege ich meine Multimedia-Inhalte aufs iPhone? Neben Videos und Sound geht es auch um dynamische Grafiken.
Und Apple hat als Lösung des Problems HTML5 propagiert. Seit dem letzten Update des App Stores, dass es verbietet, das finanzielle Transaktionen in Apps am Marketplace vorbeilaufen,
suchen Firmen wie Amazon nach einer Alternative um auf dem iPhone weiterhin vertreten zu sein.
Neben den 3 Tags Audio, Video und Canvas gibt es noch andere Features, wie LocalStorage, Offlinemodus und Websockets, welche ich bald auch im GWT erhoffe.
Auch die Branche der Browser- und Socialgames wird wohl kaum an HTML5 vorbeikommen. Zwar scheint dort Flash der Platzhirsch zu sein, das wird sich aber wohl in den nächsten Jahren ändern. Vielleicht schon mit der Version 9 des böses Browsers.
Dass es durchaus möglich ist, mit HTML5 schicke Sachen zu erstellen, soll eine meine kleine Demo zeigen:
http://myasciigenerator.appspot.com/
Ich hab das “Preload” Problem von Canvas nocht nicht ganz behoben, aber es ist auch nur eine Demo.
Grafiken und Sounds stammen aus dem Open-Source Game “Battle for Wesnoth“.
HTML5 kann und wird ein Flashkiller sein und GWT das Framework für Browsergames der Zukunft.
Oder seid ihr anderer Meinung?
Datenbankzugriffe sind teurer als Speicherzugriffe, das ist nicht neu. Viele Frameworks wie Hibernate setzen deswegen auf einen Cache, um die Anzahl der Datenbankzugriffe zu minimieren und damit die Performance zu erhöhen. Das Caching passiert dabei meißt unter der Haube und lässt den Entwickler den Fokus auf die eigentlichen Arbeiten behalten.
Mit Google App Engine und Memcached und dem verteilten Cache ist Caching auch in der Cloud möglich. Doch auch wenn bei App Engine keine Persistenzlösung wie Hibernate oder EclipseLink möglich ist, kann man auf eine einfache Weise Caching nachrüsten.
Eine einfache DAO-Klasse
public class NodeDAO { public Node load(long id) { // code } public Node save(Node node) { if (node.getId() == 0) { insert(node); } else { update(node); } return node; } public void delete(Node node) { // code } private void insert(Node node) { // code } private void update(Node node) { // code } }
Relativ einfach, aber erfüllt den Zweck.
Zunächst erstellen wir ein Interface Indexed, damit die Lösung später für verschiedene Klassen möglich ist.
public interface Indexed { public long getId(); }
Und einen Simplen Cache (hier kann man später auf MemCached umrüsten)
public class SimpleCache { static HashMap cache; public static HashMap getInstance(){ if (cache==null){ cache = new HashMap(); } return cache; } }
Als Schlüssel soll hier Klassenname und ID fungieren
Noch ein paar kleine Interfaces für die 3 Cache- bzw Datenbankfunktionen
@Retention(RetentionPolicy.RUNTIME) public @interface SelectCachable {} @Retention(RetentionPolicy.RUNTIME) public @interface SaveCachable {} @Retention(RetentionPolicy.RUNTIME) public @interface DeleteCachable {}
Ein bisschen Guice-Magie
Starten wir mit dem SELECT oder GET – Befehl. Wenn wir einen Datensatz geladen haben, soll der im Cache verewigt werden. Ist er schon im Cache, soll keine Datenbankverbindung hergestellt werden. Wir benutzen den MethodInterceptor.
public class SelectCacher implements MethodInterceptor{ public Object invoke(MethodInvocation call) throws Throwable { Object[] args = call.getArguments(); Object result; if (args.length==1 && args[0] instanceof Long && SimpleCache.getInstance().containsKey(call.getMethod().getReturnType()+ "@" + args[0])){ // aus dem Cache holen result = SimpleCache.getInstance().get( call.getMethod().getReturnType()+ "@" + args[0]); }else{ // Aus der DB Holen result = call.proceed(); SimpleCache.getInstance().put( call.getMethod().getReturnType()+ "@" + args[0],(Indexed) result); } return result; } }
Auch der DELETE-Befehl ist simpel:
public class DeleteCacher implements MethodInterceptor { public Object invoke(MethodInvocation call) throws Throwable { Object[] args = call.getArguments(); Indexed indexer = (Indexed) args[0]; if (args.length==1 && SimpleCache.getInstance().containsKey(indexer.getClass()+ "@" + indexer.getId())){ SimpleCache.getInstance().remove( indexer.getClass()+ "@" + indexer.getId()); } return call.proceed(); } }
Zuletzt noch der PUT Befehl, hier muss man dazu sagen, dass aufgrund der ID entschieden wird, ob ein Insert oder Update geschieht, beim Insert wird bei @@IDENTITY die ID bestimmt und dem Objekt zugewiesen.
public Object invoke(MethodInvocation call) throws Throwable { Object result = call.proceed(); Indexed indexer = (Indexed) result; SimpleCache.getInstance().put(indexer.getClass() + "@" + indexer.getId(), indexer); return result; }
Nun müssen wir noch die Annotationen mit den Interceptors verbinden. Das passiert bei Guice so:
public class CacheModule extends AbstractModule{ protected void configure() { bindInterceptor(any(), annotatedWith(SelectCachable.class), new SelectCacher()); bindInterceptor(any(), annotatedWith(SaveCachable.class), new SaveCacher()); bindInterceptor(any(), annotatedWith(DeleteCachable.class), new DeleteCacher()); } }
Der finale Schritt, jetzt verbinden, oder besser gesagt injizieren, wir alles, was bisher erstellt wurde. Per Factory-Pattern erhalten wir wir nun eine Erweiterte Variante der Basisklasse. Per Annotationen bestimmen wir, welcher Methode welcher Interceptor zugewiesen wird.
public class NodeDAO { public static NodeDAO create() { Injector inj = Guice.createInjector(new CacheModule()); NodeDAO ret = inj.getInstance(NodeDAO.class); return ret; } @SelectCachable public Node load(int id) { // Code } @SaveCachable public Node save(Node node) { if (node.getId() == 0) { insert(node); } else { update(node); } return node; } @DeleteCachable public void delete(Node node) { // Code } private void insert(Node node) { // Code } private void update(Node node) { // Code } }
Mit Google Guice Funktionalitäten nachrüsten ist recht einfach. Die Lösung ist noch nicht ideal, aber ein guter Start, da alle Komponenten austauschbar sind.
Ich interessiere mich in letzter Zeit sehr für das Thema “Cloud-Computing“, vor allem aber für “Google App Engine“.
Die Idee in einer “Adminfreien” Zone zu entwickeln und Google “den Rest tun lassen” besticht einfach.
Das System ist in sich schlüssig und einfach zu verstehen, lediglich einige Einschränkungen sind da.
Vor allem die Entscheidung für BigTable als Datenbank bereitet da ein paar Umstellungsprobleme.
Kein COUNT und AVG mehr in SQL-Queries benutzen zu können ist schon etwas ungewohnt.
“Tu Nichts Böses” ein Leitsatz von Google.
Und weil Google auch nicht möchte, dass jemand anderes Böses tut, hat man diesen Leitsatz mit in die AGBs aufgenommen.
Dort heißt es :
2.2. Your use of the Service must comply with all applicable laws, regulations and ordinances, including any laws regarding the export of data or software. You agree not to use the Service in the design, development, production, or use of missiles or the design, development, production, stockpiling, or use of chemical or biological weapons. You agree not to use the XMPP API to operate or to enable any telecommunications service or in connection with any applications that allow users to place calls to or receive calls from any public switched telephone network.
Frei übersetzt:
Man verpflichtet sich, Google App Engine nicht zur Entwicklung oder zum Bau von Raketen, chemischen oder biologischen Waffen zu verwenden.
O No Devil
(Viele halten ja Google’s Leitsatz für ein Anagram für ebenjenes.)
Ich wusste ja gar nicht wie mächtig die Struktur von Google ist, wenn es möglich ist mit einem Hostingservice in der Lage zu sein,
Raketen zu bauen. Tatsächlich habe ich mit dem Projekt AppRocket ein erstes Indiz für eine solche Möglichkeit gefunden.
Auch dieser Ausschnitt bei Google Maps deutet eindeutig daraufhin:
Größere Kartenansicht
P.S:
Ja hier ist Ironie versteckt.

Categories
Tag Cloud
Blog RSS
Comments RSS
Last 50 Posts
Back
Back
Void « Default
Life
Earth
Wind
Water
Fire
Light 