Dienstag, 25. Dezember 2012

GWT: Cell in Celltable dynamisch verändern

GWT 2.5

Wenn die Anforderung laute je nach Cell Value Veränderungen z.B. in der Farbe der Schrift vorzunehmen habe ich eine Lösung gefunden, die wahrscheinlich nicht ideal ist, die ich nichtsdestotrotz hier vorstellen möchte.

Als erstes möchte ich die TextInputCell etwas erweitern, in diesem Fall zum zweiten Mal, da ich vorher schon Ausbauten brauchte, der wichtige Punkt ist in jedem Fall dass ein eigenes Template gestaltet werden kann:


public class MyTextInputCell extends ExtendendedBrowserEventsTextInputCell {

 interface Template extends SafeHtmlTemplates {
  @Template(<input type=\"text\" value=\"{0}\" tabindex=\"-1\" size=\"{1}\" maxlength=\"{1}\" style=\"color:{2}\"></input>")
  SafeHtml input(String value, String size, String textColor);
 }

Zu beachten ist, das die Farbe über style geändert wurde, einfach die color reinzuschreiben reichte aus irgend einem Grund nicht.
Das Ganze kommt dann in der überschriebenen Methode render zum Tragen:


@Override
 public void render(com.google.gwt.cell.client.Cell.Context context, String value, SafeHtmlBuilder sb) {
  // Get the view data.
  Object key = context.getKey();
  ViewData viewData = getViewData(key);
  if (viewData != null && viewData.getCurrentValue().equals(value)) {
   clearViewData(key);
   viewData = null;
  }

  String s = (viewData != null) ? viewData.getCurrentValue() : value;
  if (s != null) {
   sb.append(myTemplate.input(s, size, textColor));
  } else {
   sb.appendHtmlConstant("<input type=\"text\" tabindex=\"-1\"></input>");
  }
 }
textColor ist dabei eine Instanzvariable, doch wann verändere ich diese entsprechend?
Ich greife da in der Column Implementierung in der Methode getValue, hier kann man schön Wertabhängig die InstanzVariable textColor verändern. Gewählt habe ich diesen Weg, weil ich ein großes Array an Namen brauche um die Farbe des Textes zu bestimmen und mir es am geschicktesten schien dieses Array der Column mitzugeben.

private static final class MyColumn extends Column<String[], String> {

  int index;
  Name[] names;

  public MyColumn(Cell<String> cell, int index, Name[] names) {
   super(cell);
   this.index = index;
   this.names = names;
  }

  @Override
  public String getValue(String[] data) {
   if (this.getCell() instanceof MyTextInputCell) {
    MyTextInputCell cell = (MyTextInputCell) this.getCell();
    if ((cell.isUserid || cell.isUseridStrict) && !Utils.isUseridInNames(data[index], this.names)) {
     cell.textColor = "red";
    } else {
     cell.textColor = "black";
    }
   }
   return data[index];
  }
 }

Es gibt sicher elegantere Methoden, ich würde mich freuen wenn jemand mir eine zeigt.

Links:
Frage dazu auf stackoverflow

Samstag, 15. Dezember 2012

GWT: SuggestBox in einer CellTable

GWT 2.5

Hat man sich einmal entschlossen eine CellTable zu verwenden und stößt dann auf Anforderungen die die CellTable nicht von vornherein vorgesehen hat kann das sehr ärgerlich werden. Mir ging es so bei der Anforderung eine SuggestBox in der Table zu verwenden.
Schlußendlich stellte sich heraus daß das Ganze gar nicht so eine Zauberei ist, muß aber auch dazusagen, daß die Lösung noch nicht wirklich den Praxistest erlebt hat.

Meine Lösung besteht darin, einfach die TextInputCell zu extenden und so eine SuggestBox reinzuschummeln:


public class SuggestBoxTextInputCell extends TextInputCell {

 MySuggestBox suggestBox;

 private class MyTextBox extends TextBox {
  public MyTextBox(Element element) {
   super(element);
  }
 }

 private class MySuggestBox extends SuggestBox {
  public MySuggestBox(SuggestOracle suggestOracle, TextBox textBox) {
   super(suggestOracle, textBox);
  }

  @Override
  public void onAttach() {
   super.onAttach();
  }
 }

 public SuggestBoxTextInputCell() {
  super();
 }


 @Override
 public void onBrowserEvent(Context context, Element parent, String value, NativeEvent event,
   ValueUpdater<String> valueUpdater) {
  super.onBrowserEvent(context, parent, value, event, valueUpdater);
  String eventType = event.getType();
  if (BrowserEvents.FOCUS.equals(eventType)) {
   TextBox textBox = new MyTextBox(getInputElement(parent));
   suggestBox = new MySuggestBox(getSuggestOracle(), textBox);
   suggestBox.onAttach();
  }
 }

 private SuggestOracle getSuggestOracle() {
        //this does not work without implementation
        return null;
 }
}

Die Methode gestSuggestOracle muss natürlich noch implementiert werden um den Beispielcode lauffähig zu bekommen.
Links:
Google Groups Beitrag
Stackoverflow Beitrag zum Thema

Donnerstag, 29. November 2012

JMeter Einschließende URL-Muster

JMeter 2.8

Zeichnet man mit dem JMeter HTTP Proxy Server einen Geschäftsfall auf liefert der Browser, bzw. oft dessen Plugin ziemliches Störfeuer.

Um das loszuwerden sind einschließende URL Muster hilfreich, damit wird viel von dem unnötigen Zeugs einfach nicht aufgezeichnet. Diese Muster sind leider nicht ganz einfach zu erraten, darum hier ein Screen:




Freitag, 23. November 2012

Einbindung von Source eines Submoduls für GWT/Maven

GWT 2.5.0
gwt-maven-plugin 2.5.0
Maven 3.0.3

Bei einem mehrmoduligen GWT/Maven Projekts ist das Model oft in einem anderen Modul als im eigentlichen GWT Modul (web Modul). Für das gwt-maven-plugin werden auf der Homepage 2 Möglichkeiten vorgeschlagen das zu lösen:

http://mojo.codehaus.org/gwt-maven-plugin/user-guide/project.html

Erster Vorschlag das Goal gwt:resources hinzuzufügen funktioniert ausgezeichnet, allerdings möchte man das Problem manchmal nicht über zusätzliche Commandline Befehle lösen sondern über die pom Konfiguration. Hier wird vorgeschlagen das ganze über das Attribut compileSourcesArtifacts zu lösen, das funktioniert aus mir nicht ganz erklärlichen Gründen nicht.

Meine Lösung war dann genau wie vorgeschlagen das zusätzliche gwt.xml im Submodul anzulegen:


  
  


 und dieses im gwt.xml des GWT Moduls zu mit "inherits" einzubinden.


Damit funktioniert das Ganze leider noch nicht, im pom.xml des Moduls, wovon das Model eingebunden werden soll muß man noch folgendes eintragen:

 
  
   
    src/main/java
    
     **/*.java
    
   
   
    src/main/resources
    
     **/*.xml
    
   
  
 



Mittwoch, 7. November 2012

Java: Deep Copy von Listen

Eine "tiefe" Kopie einer beliebigen Liste in Java ist gar nicht so selbstverständlich wie man meinen möchte, die meisten Ansätze kopieren nämlich zwar die Liste, aber der Inhalt bleibt Referenz und somit wird die Kopie nicht "tief".

Eine kleine Methode löst mir das Problem:

public static List<ResultLine> deepCopyListResultLine(List<ResultLine> list) {
  List<ResultLine> resList = new ArrayList<ResultLine>();
  for (ResultLine line : list) {
   resList.add(new ResultLine(line));
  }
  return resList;
 }


Voraussetzung ist natürlich dass das Objekt über einen Konstruktor verfügt der diese Art der Duplizierung möglich macht:

public class ResultLine implements Serializable {

 public ResultLine() {

 }

 public ResultLine(ResultLine line) {
  this.plz = line.getPlz();
  this.app = line.getApp();
  this.eighty = line.getEighty();
  this.eightyAnz = line.getEightyAnz();
  this.firstTen = line.getFirstTen();
  this.firstTenAnz = line.getLastTenAnz();
  this.lastTen = line.getLastTen();
  this.lastTenAnz = line.getLastTenAnz();
  this.ldkz = line.getLdkz();
  this.makler = line.isMakler();
  this.mobile = line.isMobile();
  this.sessionAnz = line.getSessionAnz();
 }

Auf diese Weise ist ein "tiefes" Kopieren kein Problem mehr.

Dienstag, 18. September 2012

GWT: *.nocache.js wird nicht gefunden

Ecplise: Indigo Service Release 2
Maven 3.0.3
Google Plugin 3.1.0
GWT SDK 2.4.0
m2e Plugin 1.0.200


Wird beim Start der Applikation das nocache.js File nicht gefunden kann das einige Gründe haben, bei mir war das Problem die Umbenennung des ganzen Projekts. Im Web Deployment Assembly des Web Moduls wurde diese Namensänderung nicht automatisch nachgezogen und so wurde natürlich das nocache.js File nicht gefunden. 

Weg zur Einstellung: Web Modul -> Rechtsklick -> Properties -> Deployment Assembly (Dort fügt man die entsprechenden Folder hinzu).





Freitag, 31. August 2012

GWT, Maven und Eclipse: Build Failure weil die Klasse mit dem Entry Point nicht gefunden wird

Ecplise: Indigo Service Release 2
Maven 3.0.3
Google Plugin 3.1.0
GWT SDK 2.4.0
m2e Plugin 1.0.200


Wer GWT mit Maven und Eclipse verwenden möchte braucht manchmal ein dickes Fell.



[INFO] Compiling module myCompany.client.Frontend
[INFO]    Finding entry point classes
[INFO]       [ERROR] Unable to find type ' myCompany.client.Frontend '
[INFO]          [ERROR] Hint: Previous compiler errors may have made this type unavailable
[INFO]          [ERROR] Hint: Check the inheritance chain from your module; it may not be inheriting a required module or a module may not be adding its source path entries properly
[INFO] ------------------------------------------------------------------------


Die Klasse existiert aber und es tritt auch kein Compile Fehler auf. Des Rätsels Lösung war der Ablageort des Frontend.gwt.xml. Wie bei Maven üblich wurde es in src/main/resources untergebracht und dort unter myCompany/client. Das mag aber nun das gwt-maven-plugin gar nicht und wirft den obigen Fehler aus. Verschiebt man das gwt.xml nun einen Folder runter in den Folder myCompany geht plötzlich der Build durch.

Freitag, 3. August 2012

Jar auf die javac -target Version überprüfen

Baut man sich ein Fat Jar zusammen und bindet dabei Third Party Jars ein gibt es derzeit in Maven keinen Warnhinweis, das einige der fremden Jars unter Umständen eine höhere Version der Runtime brauchen als als Zielplattform vorgesehen/möglich ist.

Hier hilft einen das Programm JarCheck, damit kann man einfach alle Klassen eines beliebigen Jars auf die benötigte Runtime überprüfen.
Hier überprüfe ich Beispielsweise ob alle Klassen auch schön im Bereich von Java 1.1 bis 1.4 liegen:


java -jar jarcheck.jar myFatJar.jar 1.1 1.4

Links:
Download JarCheck


Samstag, 9. Juni 2012

Maven - Maven Integration for WTP installieren

Maven Integration for WTP 0.15.2.20120306-2040
Rational Application Developer 8.0.4

Will man die Maven Integration for WTP installieren muß man http://download.eclipse.org/webtools/repository/indigo in seinen Update Sites drinnen haben und diesen Haken gesetzt haben:



Ansonsten kommt eine Fehlermeldung über eine bennötigte Abhängigkeit:

Missing requirement: JavaScript Development Tools

Link:
m2e-users Mail Archiv
WTP Update Site  http://download.jboss.org/jbosstools/updates/m2eclipse-wtp/


Donnerstag, 24. Mai 2012

CVS Changelog Plugin für Eclipse/RAD

RAD 8.0.1
ChangeLog 1.0.2.201204231239


Unter Eclipse/RAD CVS-Commits für ganze Projekte anzuzeigen funktioniert nicht, das Plugin CVS Change Log for Eclipse konnte man früher ganz gemütlich in ein Plugin Verzeichnis einspielen und schon hatte man die entsprechende Funktion zur Verfügung. Für RAD 8.0.1 hat das nicht funktioniert.

Glücklicherweise gibt es ein anderes Projekt mit entsprechender Update Site, wo man einfach nur eine URL unter Help/Install new Software... eintragen muß und schon hat man die Funktionalität auch im RAD wieder zur Verfügung:

http://svn.codespot.com/a/eclipselabs.org/changelog/trunk/org.eclipselabs.changelog.update-site/

Links:
Das Projekt auf Google Code



Donnerstag, 17. Mai 2012

GWT, Eclipse und Maven - Ein Skeleton Projekt anlegen

Maven 3.0.3
Eclipse Java EE IDE for Web Developers Indigo Service Release 2 20120216-1857
gwt-maven-plugin 2.4.0
build-helper-plugin 1.7
m2e - Maven Integration for Eclipse 1.0.200.20111228-1245
Google Plugin for Eclipse 3.7 2.6.1v20205091048-rel-r37

Will man mit dem org.codehaus.mojo.gwt-maven-plugin Archetype ein Skeleton GWT Projekt erzeugen kann das ein ziemlicher Task sein. Irgendwie hab ich das trotzdem hinbekommen, es gibt sicher andere und wahrscheinlich auch bessere Wege, aber ich beschreibe mal wie ich vorgegangen bin.

Zuallererst: Das m2eclipse Plugin von Sonatype muß deaktiviert oder deinstalliert werden, es ist meiner Meinung nach einer der Hauptgründe warum es so schwierig ist das Ganze hinzubekommen.

Dann ein neues Maven Projekt anlegen und den Archetype gwt-maven-plugin  verwenden:



Danach füge ich im pom.xml mit dem build-helper-maven-plugin den zu generierenden Code zum Sourcepath hinzu (m2eclipse ignoriert das einfach, einer der Gründe, warum es raus mußte). Beim Probelauf für diesen Blogeintrag hatte das Projekt danach trotz deaktivierten m2e eine Maven Nature (am hinzugefügten M erkenntbar). Diese habe ich einfach deaktiviert, dann muckste m2e auch wirklich nicht mehr auf (Rechter Mausklick aufs Projekt -> Maven -> Disable Maven Nature).




 org.codehaus.mojo
 build-helper-maven-plugin
 1.7
 
  
   add-source
   generate-sources
   
    add-source
   
   
    
     ${project.build.directory}/generated-sources/gwt
    
   
  
 


Dann baue ich mir einen Launcher für das externe Maven und lasse das Ganze mal mit dem Goal install laufen:


Der Lauf geht inklusive Tests durch, auch die generierten Sourcen sind eingebunden, sieht einmal sauber aus.
Nun probiere ich das Ganze auch mal mit den Mavengoals clean gwt:run laufen zu lassen und siehe da, es funkt:

Auch im Browser sieht das sauber aus:

Im Prinzip nicht viel zu tun, es hat allerdings schon seine Zeit gebraucht bis ich mich durchgerungen habe das an sich tolle m2eclipse Plugin zu deaktivieren.

Am Ende noch der Projektbaum, wie er aussieht wenn alles gut gegangen ist:



Links:
Homepage gwt-maven-plugin
GWT Working with Maven

Freitag, 11. Mai 2012

Maven: Common Ressourcen ins Projekt kopieren

Maven 3.0.3
maven-dependency-plugin 2.3
maven-resources-plugin 2.5

Händisches kopieren von Ressourcen  aus einem allgemeinen Projekt in ein spezifisches Projekt kann sehr nervig werden, darum hab ich das mal automatisiert. Erster Task ist, das im Repository nur das jar rumliegt, das muß man sich holen und entpacken. Das kann das maven-dependency-plugin für einen erledigen:



 maven-dependency-plugin
 2.3
 
  
   unpack-webapp-commons-resources
   process-resources
   
    unpack
   
   
    
     
      com.xxx.frameworks
      xxx-webapp-commons-resources
      jar
      true
      
       ${project.build.directory}/temp
      
     
    
   
  
 


Danach holt mann sich das Benötigte mit dem maven-resources-plugin aus dem entpackten Projekt und kopiert es an die benötigten Stellen:


 maven-resources-plugin
 2.5
 false
 
  
   copy-cms
   process-resources
   
    copy-resources
   
   
    true
    ${basedir}/src/main/webapp/cms
    
     
      ${basedir}/target/temp/cms
     
    
   
  
  
   copy-css
   process-resources
   
    copy-resources
   
   
    true
    ${basedir}/src/main/webapp/css
    
     
      ${project.build.directory}/temp/css
      
      
       test/bla.css
       test2/include/*.css
      
     
    
   
  
 


Zu beachten ist dann noch, das die kopierten Ressourcen wahrscheinlich ins SCM reinrutschen sollen. Will man um alles wirklich sauber zu machen am Beginn des Builds die alten kopierten Files noch löschen macht man das so: Beitrag zum Löschen von Files in der clean Phase des Maven Builds

Maven: clean erweitern, aber .cvsignore behalten

Maven 3.0.3
maven-clean-plugin 2.4.1

Commons Ressourcen lasse ich mir im Laufe des Mavenbuilds reinkopieren, allerdings sollte vorher ausgemistet werden, falls nämlich Ressourcen umbenannt wurden kommt es zu Doppelgleisigkeiten, die besonders bei Javascript Ressourcen sauber weh tun können.

Leider treiben sich zwischen meinen Commons auch applikationsspezifische Ressourcen herum, darum kann nicht alles einfach weggeworfen werden. Dazu zählen im besonderen auch die .cvsignore Files, die verhindern das mir meine Commons, die ja eh bei jedem Build aus dem Commons-Projekt umkopiert werden, ins CVS rutschen.


   
    maven-clean-plugin
    
     
      
       src/main/webapp/cms
       false
       
        **/*.pdf
        **/.cvsignore
        **/CVS
        **/CVS/**
       
      
     
    
   


Vor allem die CVS Folder darf man nicht vergessen, die werden in Eclipse ja nicht angezeigt.

Links:
stackoverflow.com Beitrag



Montag, 7. Mai 2012

Maven: Test Source generieren und damit testen

Maven 3.0.3
exec-maven-plugin 1.2.1

Beim Beispielprojekt handelt es sich um einen Source Code Generator, der aus einem File, das Text in einer Domain Specific Language enthält, Java Code generiert.

Soweit so gut, nun soll beim Build aus einigen Test DSL Files der Source Code erzeugt werden und gegen einige JUnit Tests gefahren werden, um zu sehen ob der generierte Code den Erwartungen entspricht.

Das Ganze war entgegen meinen ersten Befürchtungen dann dank Maven einfach, dafür gibts das exec-maven-plugin.

   
    org.codehaus.mojo
    exec-maven-plugin
    1.2.1
    
     
      
       java
      
      generate-test-sources
     
    
    
     com.xxx.xxxx.gen.Action
     src/test/java/gen
    
   
  

Hier wird die Main Methode der angegebenen Klasse ausgeführt, in meinen Fall Test Source an der richtigen Stelle erzeugt (Das ist in der Klasse festgelegt, wird hier eigentlich nur dadurch bedacht das testSourceRoot angegeben wurde, damit Maven auch sicher mitkriegt das dieser Code vor dem Test auch brav kompiliert wird). Einfacher gehts eigentlich nimmer.

Damit vom generierten Code nicht irgendwann störende Restbestände herumliegen lösche ich diese bevor neuer generiert wird mithilfe des maven-clean-plugin:



    maven-clean-plugin
    
     
      
       src/test/java/gen
       false
      
     
    
   

Das wars eigentlich.

Was etwas irritieren kann ist, daß vor dem Build immer unkompilierbarer Code herumliegt, damit die JUnit Tests kompilieren muß erst der Test Source generiert werden.



Maven: Build soll zu Ende geführt werden, auch wenn Tests fehlschlagen

Maven 3.0.3

Hierbei hilfreich hat sich der Parameter maven.test.failure.ignore erwiesen, einfach auf true setzen und schon läuft der Build auch bei Test Failures zu Ende und schließt sogar mit Success ab, wenn sonst nix Störendes passiert.

Links:
stackoverflow Beitrag zu diesem Thema



Dienstag, 24. April 2012

Debuggen von Maven Integrationstests

IBM RAD 8.0.1 (Eclipse 3.6)
Maven 3.0.3
maven-jetty-plugin 6.1.26
selenium-maven-plugin 2.2
maven-surefire-plugin

Ich erstelle mir Integrationstests mit dem Seleniumplugin des Firefox (export TestCase as JUnit 4 (Webdriver)), bearbeite diese nach und lasse sie mit dem maven-jetty-plugin, selenium-maven-plugin und maven-surefire-plugin laufen.

Manchmal möchte man dann doch in seine Tests und in die zu testende Webapp reindebuggen, allerdings werden die Breakpoints ignoriert.

Abhilfe kann man schaffen, indem man im surefire-plugin den forkMode konfiguriert:







Obwohl Maven nicht embedded in der IDE läuft sondern über das m2eclipse Plugin eine externe Version gewählt wurde kann man sich nun kreuz und quer durch den Code debuggen.

Links:
stackoverflow.com maven-surefire-plugin-fork-mode



Freitag, 30. März 2012

Ubuntu: bundle install schlägt fehl

Rails 3.0.11
Ruby 1.9.2
Ubuntu 11.10

Nachdem "bundle install" wegen dem Gem nokogirl fehlgeschlagen ist holt man sich die fehlenden Pakete, die Ubuntu zum kompilieren braucht, so:

sudo apt-get install libxslt-dev libxml2-dev

Dann muckt es bei dem Gem "pg", da installiert man einfach wieder Pakete, die Ubuntu zum kompilieren braucht:

sudo apt-get install libxslt-dev libxml2-dev

Dann gab es noch Probleme mit dem Gem win32console, die mußte aber nur im Gemfile auskommentiert werden.


Links:
http://nokogiri.org/tutorials/installing_nokogiri.html
http://i.justrealized.com/2010/install-pg-gem-postgresql-ubuntu/

Mittwoch, 21. März 2012

Apatana Studio: Terminal einrichten

Aptana Studio 3, build: 3.0.9.201202141038
Git 1.7.6
Windows 7

Der Terminal (Windows/Show View/Terminal) scheint unter Windows nicht von Beginn an zu funktionieren. Lösung war unter Windwos/Preferences/Team/Git den Pfad zu git.exe anzugeben, schon funktioniert der Terminal.



Links
Aptana Studio Support Beitrag

Dienstag, 20. März 2012

RubyOnRails: Projekt anlegen hinter Proxy

RailsInstaller 2.1.0

Will man ein Projekt  anlegen (rails new projectname) hinter einem passwortgeschützen Proxy ist beim "bundle install" Script oft Schluß, da man sich nicht mit rubygems.org verbinden kann.

Abhilfe schafft es, den Proxy in 2 Files einzutragen

  • RailsInstallerOrdner/RubyOrdner/setup_environment.bat
  • ~/.gitconfig

In setup_environment.bat trägt man ein:

set HTTP_PROXY=http://username:password@xxx.xxx.xxx.xxx:xxxx

In .gitconfig fügt man hinzu:

[http]
proxy = http://username:password@@xxx.xxx.xxx.xxx:xxxx

Damit sollte man nun das Projekt anlegen können.

Links:


Sonntag, 18. März 2012

Aptana kann nicht auf github pushen

Aptana Studio 3, build: 3.0.9.201202141038
Git 1.7.6
Windows 7

Obwohl im Aptana Studio unter Windows/Preferences/General/Network Connections/SSH alles korrekt eingetragen ist, auf GitHub der Public Key hinterlegt wurde, läßt sich einfach nicht auf GitHub pushen, es gibt ständig diese Fehlermeldung:
Permission denied (publickey). fatal: The remote end hung up unexpectedly 
Die Lösung war, den Inhalt von ~/.ssh, wo der Public Key abliegt (dessen Pfad auch im Aptana Studio eingetragen war), in das .ssh Verzeichnis der git Installation zu kopieren. Schon funzt es.

Scheinbar ist es Aptana Studio ziemlich schnurz daß man das .ssh Verzeichnis richtig in den Einstellungen angibt, verwendet wird das .ssh Verzeichnis der Git Installation.

Links:
Aptana Studio Support Beitrag

Freitag, 9. März 2012

Problem beim Auslesen eines Blobs aus SQLite: invalid stream header

org.xerial.sqlite-jdbc 3.7.2
mysql-connector-java 5.1.18

Ursprünglich habe ich das Speichern und Auslesen eines Objekts für eine MySql Datenbank geschrieben, aber um das ganze ohne laufenden MySql Server testbar zu machen wollte ich einfach auch eine sqLite Datenbank als Alternative zur Verfügung haben. Ich habe nicht schlecht gestaunt, als derselbe Code, der für MySql einwandfrei funktionierte, bei SQLite beim Auslesen des Blobs eine Fehlermeldung warf:

java.io.StreamCorruptedException: invalid stream header: 61742E75 at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:797) at java.io.ObjectInputStream.(ObjectInputStream.java:294)

Nachlesen in Foren ergab, dass ObjectInputStream nicht funktioniert wenn die Daten nicht zuvor mit ObjectOutputStream der Datenbank übergeben wurden.

Hier mein ursprünglicher Code zum Einspielen des Objects:

public static void insertIntoTable(BigInteger id, SessionData sd, byte[] rtsd, IvissWorker ivissWorker) {
    PreparedStatement pstmt = null;
    Connection con = null;
    try {
        con = getConnection();
        pstmt = con
                .prepareStatement("REPLACE INTO iviss_session_table (id, ivissblob, rtblob, lastaccess) VALUES(?,?,?,?)");
        pstmt.setLong(1, Long.parseLong(id.toString()));
        pstmt.setObject(2, sd);
        pstmt.setObject(3, rtsd);
        pstmt.setDate(4, new Date(System.currentTimeMillis()));
        pstmt.executeUpdate();
    } catch (SQLException e) {
        ivissWorker.getIvissWorkerOutputHandler().addError(Constants.ERROR_205, "", DbConfiguration.getDbUri());
    } finally {
        try {
            if (pstmt != null) {
                pstmt.close();
            }
            if (con != null) {
                con.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

Beim Auslesen aus einer SQLite Datenbank schlug dann das Erzeugen des ObjectInputstream fehl:

public static SessionData getIvissSession(BigInteger id) throws IvissDatabaseException {
    SessionData sd = null;
    PreparedStatement pstmt = null;
    Connection con = null;
    try {
        con = getConnection();
        pstmt = con.prepareStatement("SELECT ivissblob FROM iviss_session_table WHERE id =?");
        pstmt.setLong(1, Long.parseLong(id.toString()));
        ResultSet rs = pstmt.executeQuery();
        while (rs.next()) {
            byte[] ivissblob = rs.getBytes("ivissblob");
            ObjectInputStream objectIn = new ObjectInputStream(new ByteArrayInputStream(ivissblob));
            sd = (SessionData) objectIn.readObject();
            objectIn.close();
        }

    } catch (SQLException e) {
        throw new IvissDatabaseException(Constants.ERROR_202);
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } finally {

        try {
            if (pstmt != null) {
                pstmt.close();
            }
            if (con != null) {
                con.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

    }

    return sd;
}

Gelöst wurde das Problem, indem ich der Datenbank das Object nicht mit .setObject übergeben habe, sondern als byte Array, das byte Array wird wiederrum mit ObjectOutputStream erzeugt, damit kam ObjectInputStream dann zurecht. Warum der MySql Treiber hier weniger Probleme macht und etwas aus dem ResultSet übergibt, mit dem der ObjectInputStream gut zurechtkommt bleibt mir ein Rätsel.

Hier die geänderte Zeile bei der Übergabe:

     pstmt.setBytes(2, IvissUtil.getBytes(sd));

Und hier die Methode die mir das byte Array erzeugt:

public static byte[] getBytes(Object obj) throws java.io.IOException {
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream(bos);
    oos.writeObject(obj);
    oos.flush();
    oos.close();
    bos.close();
    byte[] data = bos.toByteArray();
    return data;
}

Links:
Frage diesbezüglich in stackoverflow

Sonntag, 5. Februar 2012

Maven: Überschreiben der Konfiguration bei Reporting Plugins

Maven 3.0.3
maven-site-plugin 3.0

Das Problem:
Im Parent pom war eine alte Version vom maven-site-plugin festgelegt und sollte im Projekt pom überschrieben werden, irgendwie war es aber nicht möglich das mit den normalen Mechanismen hinzukriegen.
Die Lösung fand ich dann in einem Sonatype Blog Eintrag.
Man überschreibt die Version einfach dadurch indem man dem Plugin eine Dependency hinzufügt, die seine eigene Version hochschraubt.

 
  
   
    org.apache.maven.plugins
    maven-site-plugin
    
     de
    
    3.0
    
     
      org.apache.maven.plugins
      maven-site-plugin
      3.0
     
    
   
  
 

Interessanterweise müssen beide Version Informationen angegeben werden, auch wenn sie ident sind, ansonsten führt es nicht zum gewünschten Ergebnis.

Donnerstag, 2. Februar 2012

Statische HashMap deklarieren und mit statischen Konstruktor initialisieren

Eine statische finale HashMap ist eine tolle Sache, aber wie befüllen?

Hier ein Codeschnipsel, das dies vorführt:

public final class Constants {
 public static final Map ERRORMAP = new HashMap();
 public static final String ERROR_500 = "f500";
 public static final String ERROR_502 = "f502";
 public static final String ERROR_503 = "f503";
 public static final String ERROR_504 = "f504";
 public static final String ERROR_505 = "f505";
 public static final String ERROR_506 = "f506";
 static {
  errorMap.put(ERROR_500, "ConvertListDef: Invalid characters before newline. Only spaces and tabs allowed.");
  errorMap.put(ERROR_502, "ConvertListDef: Missing '='");
  errorMap.put(ERROR_503, "ConvertListDef: Value does not comply with naming convention");
  errorMap.put(ERROR_504, "ConvertListDef: Syntactically invalid Attributename");
  errorMap.put(ERROR_505, "ContextDef: Name of context invalid");
  errorMap.put(ERROR_506, "ContextDef: Name of contextproperty invalid");
 }
}

Der Zauberbereich ist der "statische" Konstruktor, der nur einmal bei Programmstart aufgerufen wird und mir meine HashMap befüllt.

Links:
Guido Krüger - JAVA 1.1 lernen - Kapitel 7
Siafoo Snippet



Samstag, 21. Januar 2012

Breakpoint Problem mit Eclipse GDB (GSF)

Windows 7 SP1 32Bit
Eclipse IDE for C/C++ Developers Indigo Service Release 1
MinGW 20111118

Probiert man in Eclipse C Code zu debuggen verwendet man normalerweise GDB, in meinem Fall blieb der Debugger zwar am ersten Breakpoint stehen, läßt man das Teil weiterlaufen kommt diese Meldung in der Eclipse Console:

*stopped,reason="breakpoint-hit",disp="keep",bkptno="1",frame={addr="0x004013fe",func="main",args=[],file="..\src\bsp10022.c",fullname="c:\ws\wsc\bsp10022\src\bsp10022.c",line="14"},thread-id="1",stopped-threads="all"
Die Einstellungen sagten mir daß ich GDB verwende:



Auch in verschiedensten Foren fand ich keine Hilfe. Dann kommentierte ich diese beiden Zeilen aus:

 setvbuf(stdout, NULL, _IONBF, 0);
 setvbuf(stderr, NULL, _IONBF, 0);

die aufgrund dieses Problems eingefügt hatte: Keine Ausgabe in der Eclipse Console für printf

Schon reagiert der Debugger wie erwartet.


Links:
GDB Homepage

Freitag, 20. Januar 2012

Keine Ausgabe in der Eclipse Console für printf

Windows 7 SP1
Eclipse IDE for C/C++ Developers Version: Indigo Service Release 1

Verwendet man unter Windows printf in seinem C Programm und erwartet sich beim Ausführen eine Ausgabe auf der Eclipseconsole muß darauf warten bis das Programm beendet ist. Sind noch einige scanf drinnen muß man die Daten "blind" eingeben.

Dieses Verhalten ist dem Windowseclipse geschuldet, Einstellungen wie man dieses Verhalten direkt in Eclipse verändern kann habe ich leider keine gefunden.

Allerdings 2 Wege wie man die Ausgabe trotzdem bekommt.
(Da in der Codedarstellung die spitzen Klammern Probleme machen habe ich in den Codebeispielen das include von stdio.h weggelassen.)

1. fflush(stdout) nach printf();


main(){
 int wahl;
 float betrag;
 printf("\n\tE U R O R E C H N E R\n");
 printf("\n1 DM --> EURO\n2 EURO --> DM");
 printf("\n\nIhre Wahl: ");
 fflush(stdout);
 scanf("%i", &wahl);
 if(wahl == 1){
  printf("Bitte DM-BEtrag eingeben: ");
  fflush(stdout);
  scanf("%f", &betrag);
  printf("\n%.2f DM sind %.2f EURO", betrag, betrag * 0.51129);
 }
 if (wahl == 2){
  printf("Bitte EURO-Betrag eingeben: ");
  fflush(stdout);
  scanf("%f", &betrag);
  printf("\n%.2f EURO sind %.2f DM", betrag, betrag * 1.95583);
 }
}



2. setvbuf in der main methode


main(){
 setvbuf(stdout, NULL, _IONBF, 0);
 setvbuf(stderr, NULL, _IONBF, 0);
 int wahl;
 float betrag;
 printf("\n\tE U R O R E C H N E R\n");
 printf("\n1 DM --> EURO\n2 EURO --> DM");
 printf("\n\nIhre Wahl: ");
 scanf("%i", &wahl);
 if(wahl == 1){
  printf("Bitte DM-BEtrag eingeben: ");
  scanf("%f", &betrag);
  printf("\n%.2f DM sind %.2f EURO", betrag, betrag * 0.51129);
 }
 if (wahl == 2){
  printf("Bitte EURO-Betrag eingeben: ");
  scanf("%f", &betrag);
  printf("\n%.2f EURO sind %.2f DM", betrag, betrag * 1.95583);
 }
}

Links:
Eclipse Forum Eintrag

Samstag, 7. Januar 2012

C Compiler für Eclipse auf Windows

Windows 7 SP1 32 Bit
Eclipse IDE for C/C++ Developers Indigo Service Release 1
MinGW 20111118

Da Eclipse keinen C Compiler mitliefert muß man diesen selbst installieren. Nachdem mehrere Versuche cygwin zur Zusammenarbeit zu bewegen gescheitert sind bin, versuchte ich es mit MinGW, und siehe da, einfach den Installer ausführen und schon steht einem in Eclipse die entspreche Toolchain zur Verfügung, das Zeug compiliert einwandfrei und auch der Debugger haut hin.

Hier der direkte Link zur letzten Version des Installers: MinGW Installer

Links:
Blogeintrag zu MinGW
MinGW Homepage
Einführung ins Debuggen (pdf)

Mittwoch, 4. Januar 2012

Java Installation Error 1723 (missing DLL)

Windows 7 (Servicepack 1) 32 Bit

Aus irgendeinem Grund ließ sich auf meinem System kein Java mehr installieren und eine alte Version nicht deinstallieren, jeder Versuch endete mit dieser Meldung:



Zahlreiche Foreneinträge sahen das Problem bei einem korrupten Windows Installer und rieten in diesem Fall zu Registry Manipulationen mit Tools oder per Hand zu Fuß, mir war das alles ein bisschen zu vage, neu aufsetzten kommt nicht in Frage, darum ganz Old Style: Java Folder von einem System wo alles klappt rüberkopiert und den bin-Ordner in den Systempfad gelegt.

Der schnellste Weg auf der graphischen Oberfläche die Path Variable zu verändern:

Windows + Pause
-> Erweiterte Systemeinstellungen
-> Umgebungsvariablen
-> in Systemvariablen die Varialbe Path bearbeiten

Nachtrag:
Nachdem diese Lösung aber nicht dazu taugt die Java-Plugins in die verschiedenen Browser reinzubekommen mußte ich wohl oder übel das 1723er Problem an der Wurzel erledigen.

Nach einigen Stunden verschiedenster Versuche funktionierte das Löschen der Java-Installations-Reste (die Ursache des Problems) mit dem Tool Revo Uninstaller Pro (eine 30 Tage Trail Version). Dort einfach nach Java suchen und alle relevanten Einträge ausmerzen, bei mir waren erst beim zweiten Durchgang wirklich alle weg, dann funktionierte die Neuinstallation von Java wieder einwandfrei.

Link:
Wikipediaeintrag zu Umgebungsvarialbe