Kategorien
java

Wenn der Redirect im Halse stecken bleibt

Gestern haben wir unseren nexus-Server auf den neuesten Stand gebracht und kurz danach funktionierten unsere ant-Skripte zum Herunterladen von Artefakten aus dem nexus nicht mehr. Das Problem war schnell gefunden, die nexus Entwickler haben den Status-Code für einen Redirect von 301 (moved permanently) auf 307 (temporary redirect) geändert. Das ist wohl moderner und kann den Client vom Caching abhalten. Leider haben die ant Entwickler das in ihren alten Versionen, die wir einsetzen, noch nicht gewusst und kommen damit nicht klar.

Da der nexus aber in einem Servlet Container läuft, kann man einen Filter einrichten, der alle Redirects mit Status-Code 307 (temporary redirect) auf den alten Wert 302 (moved temporarily) ändert.

Kategorien
Allgemein

Immer eins nach dem anderen

Ein kleines Beispiel zeigt, wo die Reihenfolge der Deklaration von Variablen in Java Klassen wichtig ist.

Auf der Tomcat Mailingliste kam heute eine Mail, in der jemand fragte, warum sein Singleton im Tomcat nicht einamlig in der JVM vorhanden war. Die Lösung war wohl, dass er zwei verschiedene Classloader benutzte und daher zwei verschiedene Instanzen.

Ein anderes Problem seines Codes war aber ganz anderer Natur. Der Code sah etwa so aus:

public class Singleton {
    private static Singleton instance = new Singleton();
    private static int counter = 0;

    private Singleton() {
         System.out.println("Counter: " + (++counter));
    }

    public static getInstance() {
        return instance;
    }

    public int getCounter() {
        return counter;
    }
}

Auf den ersten Blick sieht das in Ordnung aus. Der Konstruktor gibt brav ein "Counter: 1" aus und man ahnt nichts böses. Bis dann ein kleiner Testfall mit jUnit aufkreuzt:

public class SingletonTest extends TestCase {
     public void testSingletonCounter() {
          Singleton instance = Singleton.getInstance();
          assertEquals(instance.getCounter(), 1,
              "Es kann nur einen geben");
     }
}

Hier wird dann plötzlich klar, dass intern der counter trotz anderweitiger Ausgabe wieder auf 0 gesetzt wurde. Das liegt daran, dass die Initialisierung der statischen Klassenvariablen der Reihe nach geschieht. Im Konstruktor ist counter also erstmal nicht definiert – implizit also null – und wird dann auf eins inkrementiert. Nach dem Konstruktor wird dann die vermeintlich noch nicht initialsierte Variable auf 0 gesetzt.

Das kann ganz schön ins Auge gehen.

Kategorien
Allgemein

Standardkodierung von JSP Seiten

Wird eine JSP Seite in ein Servlet übersetzt und dann auch noch von einem Browser aus aufgerufen, so sind etwa vier Kodierungen durchlaufen.

Zuerst wird aus einer JSP Seite eine Java Klasse erzeugt. Hierfür findet eine Konvertierung von ISO-8859-1 nach UTF-8 statt. Will man eine andere Kodierung in der JSP Seite pflegen, so muss das mit einer pageEncoding Anweisung angegeben werden.

Dann wird aus der Java Klasse der JavaVM Bytecode erzeugt. Hier findet – so die Java Klasse in UTF-8 kodiert ist – keine konvertierung statt. In der JavaVM ist dann alles in Unicode.

Nun kommt der spannende Augenblick und ein Browser greift auf das übersetzt JSP-Servlet zu. Die Kodierung der HTTP-Anfrage des Browsers wird genutzt um die Daten der Anfrage vom Servlet-Container in Unicode zu wandeln.

Für die Reise zurück wandelt eine JSP Seite dann den Datenstrom – so nichts anderes vorgegeben – wieder in ISO-8859-1 um.

Um das ganze noch ein wenig spannender zu gestalten, ist die Standard-Kodierung von JSP Dokumenten – also XML-basierte JSP’s – natürlich UTF-8.

Seltsam also, das normalerweise so wenig Kodierungs-Probleme auftreten.

Kategorien
Allgemein

Refcards

Wenn man sich immer mal wieder fragt, wie hiess noch mal der Befehl, oder die welche Tastenkombination war die richtige?

Auf http://refcards.com/ gibt es jede Menge etwa A4 grosser PDF Dateien zu unterschiedlichen Themen, wie perl, javascript oder auch Firefox.

Da lohnt es sich auf jeden Fall mal vorbeizuschauen.

Kategorien
Allgemein

Gefilterte Listen

sind keine Neuigkeit und daher auch schon von anderen Implementiert.

Ich wollte aus einer Liste von Elementen nur ganz bestimmte Elemente holen und über diese direkt iterieren. Da die Elemente immer wieder nach unterschiedlichen Kriterien gefiltert werden sollten, dachte ich mir dass ich das ja verallgemeinern könnte. Eventuell mit einem Filter Interface:

interface Filter<T> {
   boolean isCase(T element);
}

Und einer allgemeinen Filterfunktion:

List<T> filterList(List<T> listOfElements, Filter<T> filter) {
   List<T> filteredElements = new ArrayList<T>();
   for (T element: listOfElements) {
      if (filter.isCase(element)) {
         filteredElements.add(element);
      }
   }
   return filteredElements;
}

Dann habe ich einfach mal filter und list und java in google eingegeben und bin (natürlich) über andere Leute mit demselben Problem und ähnlichen Ansätzen gestossen.

Bei google-collections und bei den jakarta-commons (mit generics). Dort werden allerdings auch direkt schon Iteratoren bereitgestellt, die filtern können und vieles mehr.

Also auch diesmal muss man das Rad nicht neu erfinden. Schade 🙂

Bei google-collections heissen die Filter im übrigen Predicates.

Kategorien
Allgemein

Warum ist immer alles so — dokumentiert

Da will man gerade eben mal ein SSO im Tomcat einbinden.

Und stellt dann fest, dass das SSO von Tomcat auf der Seite selber so gut wie gar nicht beschrieben ist. Nunja, im Netz findet man sehr schnell viele Referenzen auf CAS. Das soll auch einem Servlet Container wie Tomcat in Bezug auf SSO auf die Beine helfen.

Und für Zope soll es auch ein Produkt geben und für Perl und PHP…

Aber wenn es dann um eine einfache Anleitung geht, eine simple Webanwendung mittels einer Realm mit LDAP und dem CAS Server zu verknüpfen, sieht die Welt nicht mehr ganz so rosig aus.

Die Doku ist in einem Wiki und anscheinend vor allem in Google, oder einfach so lang, dass ich die entscheidenden Passagen beim Überfliegen nicht mehr gefunden habe.

Nun haben wir eine CAS ähnliche Lösung selber gestrickt. Aber hoffentlich finde ich doch noch DIE einfache Anleitung.

Kategorien
Allgemein

Java Vortrag 1.Teil

Im ersten Teil von Immo’s Vortrag ging es um die einfachsten Sprachkonstrukte in Java.

Immo hat uns ein wenig über Java erzählt. Zuerst nur die rudimentären Programmsteuerungs Konstrukte.

Simplestes Java-Programm. Ein Objekt mit einer statischen Start Routine:

public class Test {
  public static void main(String[] args) {
       /*Startroutine*/
  }
}

Methoden, Instanz und Klassenvariablen:

class Person {
  //Klassenvariable
  private static int anzahlPersonen = 0;
  //Instanzvariable
  private String name;

  public getName() {
    //Methodenvariable
    String defaultName = "niemand";
    return this.name!=NULL?this.name:defaultName;
  }
}

Schleifen:

int i=10;

while (i>0) {
  System.out.println(i);
  i=i-1;
}

for (i=0; i<10; i++) {
  System.out.println(i);
}

Bedingungen:

if (1==1) {
  /* wahr */
} else {
 /* falsch */
}