Andrey Hihlovskiy
Professional blog on groovy, gradle, Java, Javascript and other stuff.
Monthly Archives: July 2013
Power of switch statement in groovy
July 31, 2013
Posted by on Very impressive (and expressive):
def x = 'test' switch(x) { case null: println 'null!' break case ~/(?i)Test/: println 'got it!' break default: println 'something else' }
here second ‘case’ does case-insensitive regex comparison. In general, case may contain any regex, collection, range or class.
Cable porn
July 24, 2013
Posted by on The best cable porn I ever have seen:
http://imgur.com/r/cableporn
Memory leaks in GradleDaemon?
July 23, 2013
Posted by on Just observation: GradleDaemon eats tremendous amout of operating memory (1.5 to 2 GB) after 2 hour uptime and repeated compilation of a large project set (approx. 200 gradle projects). I’m just wondering if it a sign of memory leaks.
Ugly bug in Linux Mint/MATE
July 23, 2013
Posted by on Whenever you switch between Firefox and Eclipse (Juno/Kepler) and window-compositing is enabled, Caja crashes. That means: menu and taskbar disappear, all Caja windows are closed. The bug is still not fixed in Linux Mint 15 Olivia. I have to switch to Cinnamon 😦
ATTENTION: Major disaster on Ubuntu Forums Web-Site – all user passwords stolen
July 22, 2013
Posted by on Solution for Grails/JDK 1.7.0_25 compatibility problem
July 19, 2013
Posted by on The previously reported problem with Grails/JDK 1.7.0_25 compatibility seems to be specific to OpenJDK. As soon as the one replaces OpenJDK with Oracle JDK, error is gone and Grails applications could be started again.
Change in JDK 1.7.0_25 breaks all grails applications
July 17, 2013
Posted by on Change in JDK 1.7.0_25 breaks all grails applications:
https://bugzilla.redhat.com/show_bug.cgi?id=976693
I just tried grails 2.2.3 – the problem is still not fixed, the application fails to start with an error message “Could not determine Hibernate dialect for database name [H2]”
Any workarounds suggesting to replace hibernate libraries don’t work.
The following additional parameter allows to start grails:
grails -noreloading run-app
But hey, it’s no fun to start in no-reloading mode! Oracle, but things back!
A happier, groovier way to parse RTF: apache_tika + XmlSlurper
July 14, 2013
Posted by on I discovered a new, easier way to parse RTF in java/groovy programs. Consider the following sequence:
1. Instantiate XmlSlurper
2. Instantiate RTFParser (of Apache Tika)
3. Parse RTF (either file or string), passing XmlSlurper to RTFParser (such passing is possible, because RTFParser expects ContentHandler interface, which is implemented by XmlSlurper).
4. Traverse RTF content groovy-style: each, find, findAll, etc.
The example:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.akhikhl.test | |
import org.apache.tika.metadata.Metadata | |
import org.apache.tika.parser.rtf.RTFParser | |
class ParseRtf { | |
def parse(String rtfText) { | |
// not validating, not ns-aware | |
XmlSlurper slurper = new XmlSlurper(false, false) | |
InputStream rtfStream = new ByteArrayInputStream(value.getBytes()) | |
new RTFParser().parse(rtfStream, slurper, new Metadata()) | |
slurper.document.'body'.p.each { p -> | |
println "Got paragraph: ${p.text()}" | |
} | |
} | |
} |
Programmatic configuration of slf4j/logback
July 11, 2013
Posted by on Now I have experience with programmatic configuration of slf4j/logback.
Task
A program must open separate log file for each processed input file.
Solution for task
Instead of configuring logback via xml, the one needs to “manually” instantiate encoders, appenders and loggers, then configure and link them together.
Caveat 1
Logback goes crazy on attempt to share encoder (i.e. PatternLayoutEncoder) between appenders.
Solution for caveat 1
Create separate encoder for each appender.
Caveat 2
Logback refuses to log anything, if encoders and appenders are not associated with logging context.
Solution for caveat 2
Call setContext on each encoder and appender, passing LoggerFactory as a parameter.
Caveat 3
Logback refuses to log anything, if encoders and appenders are not started.
Solution for caveat 3
encoders and appenders need to be started in the correct order, i.e. first encoders, then appenders.
Caveat 4
RollingPolicy objects (i.e. TimeBasedRollingPolicy) produce strange error messages like “date format not recognized”, when they are not attached to the same context as appender.
Solutin for caveat 4
call setContext on RollingPolicy same way as on encoders and appenders.
Here is working example of “manual” logback configuration:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package testpackage | |
import ch.qos.logback.classic.Level | |
import ch.qos.logback.classic.Logger | |
import ch.qos.logback.classic.LoggerContext | |
import ch.qos.logback.classic.encoder.PatternLayoutEncoder | |
import ch.qos.logback.core.ConsoleAppender | |
import ch.qos.logback.core.rolling.RollingFileAppender | |
import ch.qos.logback.core.rolling.TimeBasedRollingPolicy | |
import org.slf4j.LoggerFactory | |
class TestLogConfig { | |
public static void main(String[] args) { | |
LoggerContext logCtx = LoggerFactory.getILoggerFactory() | |
PatternLayoutEncoder logEncoder = new PatternLayoutEncoder() | |
logEncoder.setContext(logCtx) | |
logEncoder.setPattern('%-12date{YYYY-MM-dd HH:mm:ss.SSS} %-5level – %msg%n') | |
logEncoder.start() | |
ConsoleAppender logConsoleAppender = new ConsoleAppender() | |
logConsoleAppender.setContext(logCtx) | |
logConsoleAppender.setName('console') | |
logConsoleAppender.setEncoder(logEncoder) | |
logConsoleAppender.start() | |
logEncoder = new PatternLayoutEncoder() | |
logEncoder.setContext(logCtx) | |
logEncoder.setPattern('%-12date{YYYY-MM-dd HH:mm:ss.SSS} %-5level – %msg%n') | |
logEncoder.start() | |
RollingFileAppender logFileAppender = new RollingFileAppender() | |
logFileAppender.setContext(logCtx) | |
logFileAppender.setName('logFile') | |
logFileAppender.setEncoder(logEncoder) | |
logFileAppender.setAppend(true) | |
logFileAppender.setFile('logs/logfile.log') | |
TimeBasedRollingPolicy logFilePolicy = new TimeBasedRollingPolicy() | |
logFilePolicy.setContext(logCtx) | |
logFilePolicy.setParent(logFileAppender) | |
logFilePolicy.setFileNamePattern('logs/logfile-%d{yyyy-MM-dd_HH}.log') | |
logFilePolicy.setMaxHistory(7) | |
logFilePolicy.start() | |
logFileAppender.setRollingPolicy(logFilePolicy) | |
logFileAppender.start() | |
Logger log = logCtx.getLogger("Main") | |
log.additive = false | |
log.level = Level.INFO | |
log.addAppender(logConsoleAppender) | |
log.addAppender(logFileAppender) | |
} | |
} |
My conclusion: logback is much easier to configure via XML. “Manual” configuration is rather tedious task and should be avoided, unless it is dictated by project needs.
Disappointment with groovy/XmlSlurper
July 10, 2013
Posted by on Greatest disappointment with groovy/XmlSlurper: it does not read/interpret XML comments. Quite critical for massive XML processing/transformations, when it is necessary to keep change delta to minimum.
In the last project I had to recede to JDOM2 – it reads, interprets and writes XML comments without problems. Sad, volume of code doubles compared to XmlSlurper.
Recent Comments