Sonntag, 6. März 2016

GIT und SVN und Windows und legacy projects

Kategorie: Das ist mein eigenes Spickzettel - schielen gestattet!


Meine letzte zwei Projekten kamen noch aus der Zeit wo Menschen freiwillig SVN eingesetzt haben :)
Wenn man aber in den Genuss des lokalen commits bereits gekommen ist, dann wird es kompliziert.
Zum einem hat man einen unbehaglichen Gefühl alles sofort global einzuchecken. Anderseits, gemachten Änderungen länger als ein paar Stunden auf dem Rechner uncommitet zu haben - ist auch be-be-be. Und das wechseln zwischen verschiedenen Versionen - das ist doch einfach geil! Jeder Zeit ohne Risiken und Sorgen, innerhalb von wenigen Sekunden auf die Vorgengenversion oder auf einen anderen Branch wechseln zu können. Und dann wieder zurück zu den aktuellen Anpassungen, ... Klasse!

Also mein Ziel ist - bei mir den GIT als SVN-Client bei einem langlaufenden Projekt einzusetzen. Am besten so, dass die anderen Entwickler, die weiterhin mit SVN-Client arbeiten, nichts von meinen Innovationen mitbekämmen. Also zumindest davon nicht gestört wären.


Default Konfiguration für Windows verbessern

git config --global user.name "Mark Stein"
git config --global user.email "m.stein@mosst.de"

# Lange Pfade ermöglichen, komisch dass das kein default Wert bei git ist
git config --system core.longpaths true

# Git soll von den Lineendigs die Hände weglassen, bitte keine Automatismus.
# Insbesondere wenn man auf Windows-Rechnern die Artifakte für Unix bauen will
git config --system core.autocrlf false




Loslegen - Das erste Checkout ala Update ala Fetch ala Pull ala Rebase

Komisch warum ein frisch geborene Entwickler sich am Anfang seines Versionierungsweges etwas verarscht fühlt. Da, allein für den Vorgang "Hol mir bitte eine Version von dem Server" zig verschiedene Mechanismen existieren.

Checkout - in SVN-Welt holt man sich dabei einen Code-Stand von dem Server herunter.
Checkout - in GIT-Welt wechselt man hiermit zwischen Versionen (Branch ist auch eine Version).
Update- nur in SVN-Welt, damit wird aktuelle Versionsstrang (trunk, branch-xy) auf die aktuellste oder angegebene Version von dem Server aktualisiert.
Fetch - nur in GIT-Welt, aktualisiert alle (oder ausgewählte) remote Versionstränge. Wichtig: lokale Versionstränge (Branches) werden davon nicht beeinflusst.
Pull - lokale Branches werden auf die Versionsstände von gemappten remote Branches gebracht. Tipp: mit git branch -vv kann dieses Mapping angeschaut werden, allerdings nicht bei SVN Repositories :( Danach suche ich noch.
Rebase -

... in Arbeit ...


Angedachte Themen:
* Arbeit mit SVN Branches: Wechsel, Merging

* Wechselwirkung mit einem weiterem Remote-Repository z.B. auf dem USB-Stick

Freitag, 9. August 2013

java.lang.NoClassDefFoundError - Aufklärung

Eine der bösesten in Java-Welt Exception ist

java.lang.NoClassDefFoundError: Could not initialize class ...


Dann weist man sofort, dass der Tag gelaufen ist und die Suche nach dem tatsächlichen Fehler ein nächtliches Debugging mit sich bringt.

Tja, dann versuchen wir an diese Stelle herauszufinden warum der Fehler so BÖSE ist, was die meiste Ursache hierfür sind und wie man es mit präventiven Maßnahmen vorbeugen kann.


Der Fehler wird so stark befurchtet vor allem wegen seinem un-sprechenden Namen. NoClassDefFoundError - was soll das schon heißen!? Sogar die Königin der Exceptions - NullPointerException - ist eindeutiger. Außerdem wird NoClassDefFoundError häufig mit dem ClassNotFoundException verwechselt und entsprechend - bekämpft man sie mit den Heilmitteln, die für das zweite pharmaziert wurden.


Die Ursache für dieses Error ist ganz trivial - die Klasse, also aufpassen die KLASSE und nicht das Objekt, könnten nicht initialisiert werden. Die Betonnung liegt dabei auf der KLASSE, weil der Error wird durch fehlerhafte Initialisierung der Attributen der Klasse verursacht. Und, wie wir alle wissen, Attribute der Klasse sind statischen Attribute (Felder).

Ein gutes Beispiel ist der Logger. Der Logger wird meistens als statisches Attribut definiert in etwa so:


public class Tester {
private static Logger log = Logger.getLogger(Tester.class);
...
}

Wenn der Logger nicht initialisiert werden kann, warum auch immer, dann kann auch die Klasse Tester nicht initialisiert werden.
Am Rande: Häufig kann der Logger nicht initialisiert werden, weil hier tatsächlich die Logger-Klasse im Classpath nicht eingebunden ist also kann die Logger-Klasse nicht geladen werden. Das ist jedoch, wie schon erwähnt, am Rande unseres Problem, da an der Stelle ist es unwichtig warum die Logger.getLogger(...) Methode eine Exception produziert hat.

Bei dem  alle ersten Zugriff auf die Tester-Klasse (z.B. über den Konstruktor new Tester()) stellt JVM, dass die Klasse Tester nicht initialisiert werden kann und merkt sich das. Ab dem zweiten Aufruf wird stets die NoClassDefFoundError Fehler produziert. Der eigentliche Fehler, dass die Logger.getLogger(...)-Methode bei dem aller ersten Aufruf fehlerhaft funktioniert hat, wird nicht mehr sichtbar.

Präventive Maßnahmen:
Die triviale Lösung fliest aus der Ursache des Problems heraus. Man sollte vermeiden statische Attributen direkt zu initialisieren.

Hier hab ich zwei Klassen verglichen, die einen Singelton abbilden, also sich selbst als statischen Attribut beinhalten.
In der ersten Klasse wird das statische Attribut zur Ladezeit der Klasse initialisiert:



Zweite Klasse initialisiert Singelton über die getInstance() Methode:



Und zum Schluss laden wir jeweils zwei Mal unsere beide Probanden  und schauen was dabei passiert:


Anbei die Konsole-Ausgaben:

Wie wir sehen - bei dem Laden der erste Klasse zum zweiten Mal kommt das NoClassDefFoundError Fehler.
Jedoch bei der zweiten Variante, wo das statische Attribute jedes Mal zur Abfragezeit geladen wird, bekommen wir stets sprechende Fehlermeldung, so dass die Ursache des Problems sofort identifiziert wird.

סוֹף~

Mittwoch, 24. Juli 2013

Java Debugging with Eclipse - Tutorial

Sehr empfehlenswerte Artikel über Java Debugging with Eclipse von Lars Vogel.

http://www.vogella.com/articles/EclipseDebugging/article.html

Insbesondere The Advanced Debugging. Es ist für mich eine Überraschung gewesen dass Teile des Programms zur Laufzeit neugestartet werden können (4.9). Und dass man Watchpoints auf Felde (Variablen) setzen kann und dadurch die Änderungen/Lesezugriffe überwachen - wusste ich auch nicht.


Donnerstag, 18. Juli 2013

Fotoalbum im Picasa publizieren und nicht im G+

Seit kurzem hat Google uns das Leben etwas komplizierte gemacht. Laut ihr (Google) sollten wir halt auf unsere einfache in Bedingung, simple und vor allem heißgeliebte Picasa-Web zu gunsten von G+ verzichten.

Nein, das machen wir nicht! ;)


Hier einpaar Schritte wie das geht. Und gleich kann man's als Tutorial für Fotoalbum publizieren verwenden.

Schritt 0:  Das kriegt man schon irgendwie selbst hin
Fotoalbum vorbereiten und hochladen und auf die Webseite von Picasa gehen:
https://picasaweb.google.com?noredirect=1
und zum Album springen.

Schritt 1: Berechtigungen bearbeiten




Für alle die den Link kriegen freischalten: "Eingeschränkt, alle mit dem Link"




Schritt 2: Link kopieren und am Ende des Links ein Parameter &noredirect=1 anhängen



Schritt Z: Einen Spende-Click auf die Werbung unten, Link verschicken an Menschen die uns lieb sind und fertig.

~Finito

Dienstag, 2. April 2013

Полезняшка : Generate Constructor using Fields

Man-o-man, wie häufig habe ich schon diese Konstruktoren geschrieben die einfach die Parameter auf Felder setzen. Das kennt doch jeder: this.hallo = hallo; Man-o-man!!! Und das geht doch so einfach:

In der Klasse, an der Stelle wo Konstruktor platziert werden soll:

ALT+SHIFT+S + O





voilà 




Donnerstag, 28. März 2013

Полезняшка : In Groß-/Kleinschreibung umwandeln

Um im eclipse eine Zeichenkette in Groß- bzw. Kleinbuchstaben zu konvertieren braucht man lediglich:
    Text selektieren und
    Lower case: CTRL+SHIFT+Y
    Upper case: CTRL+SHIFT+X

~

Montag, 4. März 2013

git merging approach

Nach dem wir von einfachem svn auf coolen git umgestiegen sind. Ging am Anfang gar nichts mehr. Das Merging mit dem eGit-Plugin und mit dem alten Rangehensweise wie bei SVN - funktionierte an der Stelle nicht.

Bei svn war das ganze schön einfach: vor dem Entwickeln einmal updaten dann anpassen, dann wieder updaten falls in Zwischenzeit jamand an der gleiche Stelle was gemacht hat - mergen und letzendilch commiten.

Bei git ist natürliche Weise alles komplizierte, oder denke ich das nur so. Auf jedem Fall habe ich nach lange Suche keinen vernünftigen Tutorial gefunden, wie das normale Arbeitsablauf mit git funktionieren soll.

Nach langem hier-und-her habe ich für uns folgende Vorgehensweise identifiziert.
Über Feedback und Hinweise, dass es auch einfache gehen kann, werde ich mich freuen.

Übrigens, ich mache jetzt alles über Konsole, da eGit bei den ersten Versuchen nicht so richtig funktioniert hat.


Das Geheimnis des erfolgreichen Mergen mit git liegt im lokalen Branch!

Also so gehe ich vor:

10: Begin:

20: Aktuelle Version des Codes herunterladen (svn update)

git pull

30: Eigenen lokalen Branch anlegen (das kann auch später gemacht werden, aber auf jedem Fall vor dem ersten add/commit)

git checkout -b FeatureXXX (Name des Branches kann z.B. der zu entwickelnde Feature oder Bug sein)


40: (Optional) Alle branches anschauen und wo man gerade arbeitet, das wird mit * vermekrt.

git branch


50: Programmieren und Entwicklen und add und commit, und add und commit ...

git add -A
git commit -m "das FeatureXXX ist schon fast fertig"


60: Wenn man fertig mit dem Feture/Fix ist, dann letztes mal commiten und zurück auf den master (trunk) switchen

git checkout master

70: Noch mal von dem remote updaten, kann ja sein dass in der Zwischenzeit jemand was gemacht und commitet hat

git pull

Jetzt haben wir im lokalen master die aktuelle Version von dem Server und im Branch FeatureXXX  unsere Anpassungen.

80: Jetzt wird gemergt, wichtig ist dass das Merging von dem master gemacht wird. Das kann mit git branch überprüft werden.
master branch, you can pruef it with "git branch")

git merge 
FeatureXXX 


90: Im Eclipse nachschauen ob wir keine Konfikte haben, dafür ist eGit gut. Die Konflikte werden mit rotem Sternchen vermerkt. Wenn wir so viel Gluck haben, das keine Konflikte entstanden sind (kann natürlich auch daran liegen, dass keine sonst außer uns was gemacht hat :) ) Dann Pushen:

git push


100: Wenn Konflikte nach dem Merging entstanden sind, dann müssen diese manuelle behoben werden und dann wie üblich: add/commit/push

git  add -A
git commit -m "F
eatureXXX ist gemerget"
git push


110:END

Ich teste erfolgreich das Vorgehen schon seit 3 Wochen.


Hier noch ein gutes Tutorial für großere Teams:
http://nvie.com/posts/a-successful-git-branching-model/


Good luck