Skip to content
accelerando

Javas String.replaceAll

21-Jul-09

The following statement

"foo baz".replaceAll("baz","$bar");

will present you an java.lang.IllegalArgumentException: Illegal group reference exception as the replacement string can contain backreferences to the search pattern as stated in Mather#replaceAll:

This method first resets this matcher. It then scans the input sequence looking for matches of the pattern. Characters that are not part of any match are appended directly to the result string; each match is replaced in the result by the replacement string. The replacement string may contain references to captured subsequences as in the appendReplacement method.

Note that backslashes (\) and dollar signs ($) in the replacement string may cause the results to be different than if it were being treated as a literal replacement string. Dollar signs may be treated as references to captured subsequences as described above, and backslashes are used to escape literal characters in the replacement string.

Luckily, there is an easy solution:

"foo baz".replaceAll("baz",Matcher.quoteReplacement("$bar"));

Turn ruby heredocs from double-quoted into sinqle-quoted strings

17-May-09

By default, Rubys heredocs are interpreted as double-quoted strings, that is #{something} is evaluated, \r turns into newline and so forth.

You can change this behaviour by single quoting the heredoc identifier like so:

s = <<-'SINGLE_QUOTED'
#{i'm not interpreted}
SINGLE_QUOTED

Batchconvert ascii to utf8

12-May-09

Next time i see umlauts in source, I’ll scream. Loud.

In the mean time I try this:

find . -iname "*.java" -exec sh -c 'iconv -f cp1252 -t utf-8 {} > {}.utf8' \;
for i in `(find . -name "*.utf8")`; do mv $i ${i/.utf8/}; done

Before you try this, make a backup of your files. It worked for me but i don’t guaranty that your files won’t vanish.

Understanding

08-May-09

I’d love to understand what makes people create abominations such as this:

if((foo ? !bar : true))
    if(!somethingelse)
        dosomething()

I don’t want to judge anyone, the thing actually worked, but i really want to understand why people don’t see that this is crap. I’m really aware of the fact, that things tends to organically grow, but how can it be achieved to raise awareness to this fact? I mean, i’m probably only a not-totally-bad engineer, but i see things that will break or are just ugly as hell and i want my colleagues to be more aware of pitfalls.

Would make life much easier and probably more conflict free.

JAX2009: Impressionen einer Konferenz (ohne Bilder)

24-Apr-09

Wie bereits im letzten Jahr war ich auch dieses Jahr 2 Tage auf der JAX, die dieses Jahr in Mainz statt fand.

Nach zahlreichen Konferenzen in den letzten Jahren, u.a. einige DOAGs, werden meine Gefühle bzgl. dieser Veranstaltungen immer gemischter. Ich habe den Eindruck, dass die Schere zwischen guten und schlechten Vorträgen immer größer klafft. Vielleicht eine Folge dessen, dass versucht wird, immer mehr Slots zu füllen.

Bemerkenswert an der JAX dieses Jahr waren natürlich Rails Day an einem Tag, Grails / Groovy Day am nächsten.

Stefan Tilkov hielt einen gut strukturierten Vortrag über REST Technologien im Rahmen des Rails Day. Das, was er präsentierte, hätte von der Thematik auch gut in einige andere Frameworks gepasst, aber trotzdem: Die Präsentation war gelungen. Gute Mischung aus wenigen Folien und Livecoding. Spätestens danach musste dem Zuhörer klar sein, was REST bedeutet. Im selben Track präsentierte Jonathan Weiss “Advanced Deployment mit Rails” in einer Art und Weise, wie ich mir keinen Vortrag vorstelle: Viel zu viele textlich überladene Folien und zumindest fürs Publikum, eine ungünstige Themenwahl. So fiel auch leider das “advanced” weg, was im Rahmen von Fragen wie “Was ist besser, JRuby oder Grails?” (Was ist besser, Apfel oder Birne?) aus dem Publikum wohl auch gut war.

Der Vortrag Rails 3 von Gregg Pollack wurde zwar in einem gänzlich anderem Stil gehalten als Stefans, war aber trotzdem hörenswert: Frei und sicher gesprochen, ohne zu langweilen.

Auch Keynotes können langweilen: Brian Kim von Liferay sprach zum Thema “Architecting your way through recession: an open source survival kit”. Ich habe nicht eine Aussage aus diesem Vortrag behalten.

Im Gegensatz dazu “Fette Maschinen brauchen schlanke Software” von Klaus Alfert, der sehr anschaulich dokumentierte, warum funktionale oder hybrid funktionale Sprachen in den nächsten Monaten und Jahren immer wichtiger werden. Auch er langweilte nicht mit Textwüsten. Passend dazu, Ted Newards “Busy Java Developer’s Guide to Scala”. Ted ist immer wieder das reinste Vergnügen: “What’s your name? – Rüdiger. – Ok, Walther.”

Was ich nicht verstehe, dass teilweise einige Redner augenscheinlich vollkommen unvorbereitet zu einer Konferenz kommen oder aber die Zuhörer mit endlosen Slides, die aussehen wie ein “man ” in Powerpoint langweilen, anstatt Slides zur Motivation zu nutzen und zur Abwechslung einmal frei zu sprechen. Die Vorträge, die mich wirklich innerlich aufgeregt oder mir wörtlich die Augen zufallen ließen, erwähne ich mal nicht namentlich.

Im Gegensatz zur DOAG ist das Publikum auf der JAX jünger und durchmischter, aber auch teilweise deutlich unhöflicher, was jedes Mal bei der Nahrungsmittelausgabe offensichtlich wurde: Sturm auf das Büffet. Oh wie ich es hasse, wenn Menschen komplett alles an Erziehung vergessen, wenn irgendwo kostenloses Essen rumsteht. Generell zum Essen: Liebe Jaxcon Menschen, lasst doch die Gimmicks wie Taschen, Rucksäcke und Zeugs sein und bestellt etwas höherwertiges Catering :)

Trotzdem, einige nette Gespräche habe ich geführt, u.a. mal ein paar Kollegen von Codecentric kennen gelernt und einen Vortrag von Mirko gehört (Flush and Clear: O/R Mapping Pitfalls), nachdem ich immer noch über die Sinnhaftigkeit eines select distinct nachdenke am manyToOne Ende einer 1-n Beziehung, um das zusätzliche Select zu sparen ;) . Desweiteren traf ich witziger weise einen Kollegen aus Ausbildungszeiten, die Welt ist wirklich klein.

Alles in allem: Eine gute Veranstaltung, 3 oder 4 Tage wären mir aber definitiv zu viel oder ich müsste mir angewöhnen, aus Vorträgen, die mich aufregen, einfach raus zu gehen. Mal schauen, wie es nächstes Jahr wird… Eventuell kann man ja bis dahin DOAG und JAX zusammenwerfen ;)

Grails: Completely disable stacktrace.log file

24-Mar-09

Regarding my question on twitter about completely disabling the creation of stacktrace.log from a Grails application in production mode, here is my answer:

environments {
    production {
        log4j = {
            appenders {
               null name:'stacktrace'
            }
        }
    }
    development {
    }
}

Be careful: This overwrites all other log4j closures that are made outside the environment specific settings. I found no solution for that.

Background: One of my Grails 1.1 app fails to start on a Tomcat application container deployed on an Oracle Enterprise Linux server because it fails to create the stacktrace.log.

What annoyed me is that i needed to dig around in the Grails source code to find the answer to my question in “src/groovy/org/codehaus/groovy/grails/plugins/logging/Log4jConfig.groovy” within the method “createFullstackTraceAppender()”. Should be stated in the documentation (perfect place here).

Edit: If your Grails 1.1 still fails to start(*) look out for xercesImpl.jar and xml-apis.jar or similar somewhere in your Tomcat 5 directory. These are some kind of Java 1.4 compatibility layers which break things in Grails 1.1. Oracle puts these into common/endorsed. After removing them, everything went fine.

(*) Exception was:

java.lang.RuntimeException: XPathFactory#newInstance() failed to create an XPathFactory for the default object model:
http://java.sun.com/jaxp/xpath/dom with the XPathFactoryConfigurationException: javax.xml.xpath.XPathFactoryConfigurationException:
No XPathFctory implementation found for the object model: http://java.sun.com/jaxp/xpath/dom

Phusion Passenger and memcache-client revisited

23-Mar-09

The last Passenger update brought some good explanation off the problems regarding Passenger and memcache-client (see here).

Smart spawning of Passenger processes creates shared file descriptors. As the connections to memcached are sockets they are shared as well so data on them gets corrupted which is explained very nicely in the Passenger documentation: Example 1: Memcached connection sharing (harmful).

The solution presented there works like a charm. The reestablish_connection_to_memcached line is actually not more than CACHE.reset where CACHE is the reference to the memcache connection.

After that change, spawning methods smart-lv2 and smart will work in connection with environment.rb configured memcache connections.

Edit: As requested in the comments, a little example:

memcache_options = {
  :c_threshold => 10000,
  :compression => true,
  :debug => false,
  :namespace => 'some_ns',
  :readonly => false,
  :urlencode => false
}
 
CACHE = MemCache.new memcache_options
CACHE.servers = '127.0.0.1:11211'
begin
   PhusionPassenger.on_event(:starting_worker_process) do |forked|
     if forked
       # We're in smart spawning mode, so...
       # Close duplicated memcached connections - they will open themselves
       CACHE.reset
     end
   end
# In case you're not running under Passenger (i.e. devmode with mongrel)
rescue NameError => error
end

In this case, CACHE is the global constant that i use to access my memcache-client.

I guess you’ll need to do the same with the global Rails.cache object, but i’m not sure. Anyway, the above solution works for me.

Grails’ withFormat block

23-Mar-09

Some things are not really different in Rails and Grails world. The pendant to Rails’ respond_to method is Grails withFormat block.

Both are supposed to render a different content type as requested according to the accept header and and the format parameter.

And both fail to some extend with Internet Explorer 5.5 to 7.0. For a longer explanation see my post on respond_to linked above. In short: First visit always gave me the an Excel File, all subsequent visits the intended html page.

I used nearly the exact solution within Grails 1.0.4 as in Rails:

withFormat {
      xls {
        // Same crap with IE 6/7 as with rails, compared to
        // http://info.michael-simons.eu/2007/08/06/rails-respond_to-method/
        if(params.format == 'xls') {
          def df = new SimpleDateFormat("yyyy-MM-dd")
 
          def report = ExcelReport.findById(params.reportId)          
          if(report == null)
            report = ExcelReport.findByBezeichnung('Absatzprognose')          
 
          response.contentType = 'application/vnd.ms-excel'
			    response.setHeader("content-disposition", "attachment;filename=some_filenname.xls")
          excelService.runExcelReport(
            report.bezeichnung,
            "some_parameter",
            response.outputStream
          )
          return
        }
      }
    }

Grails 1.1 seems to have fixed some issues on this case and a default or empty html {} block in front of any other format like so will do the trick:

withFormat {
      html {
        // depending on your needs
      }
      xls {
        // funny excel stuff
      }
    }

Wütend

25-Feb-09

Oh man, ich bin so verdammt wütend, ein Tweet reicht nicht aus.

Es ist so zum kotzen, dass es Programmiersprachen wie PHP den Leuten so leicht machen, hübsche Sachen zu programmieren, die auseinander fallen, wenn man sie mal schief anschaut.

“Hübsche Gui” und “Ich weiß, was ich da gerade in die Datenbank schreibe” sind zwei Paar Schuhe.

Wie kann man eigentlich eine Checksum Routine so implementieren, dass sie auf unterschiedlichen Architekturen unterschiedliche Ergebnisse liefert? Braucht es da mehr als einen mittelmässig begabten Affen, zu erkennen, dass das eine scheiß Idee ist? Und noch spannender ist es natürlich dann, diese Funktion auch zu nutzen.

Boah echt ey.

Leute, lasst die Finger von PHPs crc32() Implementierung oder benutzt sie richtig.

Frustration

25-Feb-09

if you want something done right, do it yourself

If you happen to use the mint tracking tool like me, be careful when migrating from a 32bit to a 64bit server or vice versa. Mint saves ip addresses and a buttload of checksums as signed long values. That bites you right in the ass when the first visitors starts arriving at your site. All from 127.255.255.255, or at last visitors with an ip starting with > 127.

If you read this post before migrating, just add the following to your migration:

ALTER TABLE mint_visit 
  MODIFY COLUMN `ip_long` BIGINT NOT NULL,
  MODIFY COLUMN `referer_checksum` BIGINT NOT NULL,
  MODIFY COLUMN `domain_checksum` BIGINT NOT NULL,
  MODIFY COLUMN `resource_checksum` BIGINT NOT NULL,
  MODIFY COLUMN `session_checksum` BIGINT NOT NULL;
 
ALTER TABLE mint_debugger   
  MODIFY COLUMN `ip_long` BIGINT NOT NULL;
 
ALTER TABLE mint_geo  
  MODIFY COLUMN `ip` BIGINT NOT NULL;
 
ALTER TABLE mint_hostnames  
  MODIFY COLUMN `ip_long` BIGINT NOT NULL;

and you’re done.

If it’s too late, change your tables as well. You then also have to delete your entire mint_visit data, as the records are already corrupted. Great fail.

However, why on earth store an ip address as a long value?!? It’s an ip address and if i want to look at it, the program needs to go the other way round. To me: It’s just stupid fucking with datatypes and problems as that is what you get if you do so. It maybe makes sense for computation of networks, but not for a statistic tool. At least, i don’t see any sense in this.

Actually, the problem is known.

Close
E-mail It