Where he blogs about his eclipse musings
Posts tagged Java
Java and Unicode monday morning blues
May 25th
Monday morning excitement. JUnit tests that pass in the IDE fail in ant and cruise servers running on all platforms.
java.lang.AssertionError:
Expected: a string containing "... text=Ç..."
got: "... text=Å..."
My immediate reaction was the encoding used by the JVM. Setting the “file.encoding” system property to UTF-8 did not help. Running the ant based tests in remote debugging mode also confirmed that the two strings were indeed different.
Since the tests used Cobertura for code coverage, the next step was to disable cobertura. Cobertura manipulates the generated byte code to add logging statements for code coverage. Still the same error.
The hidden gem seemed to be the -encoding java compiler flag. Setting it to UTF-8 fixed the problem.
So the next time you have something fail because of an encoding issue, it could just be the compiler encoding and not just the encoding used in the runtime!
Growl notifications from ant
Jul 9th
If you use ant to run your builds, and would like to receive growl notifications about execution status, presenting Growl notifications for ant.
All you need to do is execute:
ant -listener com.google.code.ant.growlnotify.GrowlListener
And you’ll need is the growlnotify binary somewhere on your path, this is bundled with the Growl binary dmg.
Java 6 on the Mac, finally
Apr 30th
So apple finally provided this update after a long time. You can download the update from http://www.apple.com/downloads/macosx/apple/application_updates/javaformacosx105update1.html.
Read more about the release notes at http://docs.info.apple.com/article.html?artnum=307403
Mockito – one of the better mocks
Mar 5th
Now that I’ve got your attention. Mockito is not just better than the other mock frameworks out there, it’s infact the best out there.
After reading a lot of noise from fellow ThoughtWorkers in the recent past about Mockito. I decided to give a yet another mock framework a try.
Here’s what I ended up writing:
public class RecorderLauncherTest extends TestCase {
private RecorderListener listener;
private RecorderLauncher launcher;
private TestRunner runner;
protected void setUp() throws Exception {
super.setUp();
listener = mock(RecorderListener.class);
runner = mock(TestRunner.class);
launcher = new RecorderLauncher(runner, listener);
}
public void testNotifiesListenerWhenLauncherStarts() throws Exception {
launcher.launch();
verify(listener).start();
}
public void testNotifiesListenerWhenExecutionFails() throws Exception {
stubVoid(runner).toThrow(new RuntimeException()).on().run();
launcher.launch();
verify(listener).start();
verify(listener).error();
}
public void testNotifiesListenerWhenExecutionCompletes() throws Exception {
launcher.launch();
verify(listener).start();
verify(listener).finish();
}
}
What’s even nicer is that it’s actual code and not strings, and refactoring tests do not break my mocks.
Good bye expect-run-verify, hello run-verify.
This looks, and reads far better than the JMock syntax, and it was love at first sight; I’m test-infested now. If you have not tried mockito as yet, I’d recommend that you do. I’m sure you’ll love it too.
Making Eclipse Plug-ins using JRuby or Groovy
Jul 27th
Read more about using JRuby or Groovy to write eclipse plugins here: http://dev.eclipse.org/blogs/wayne/2007/07/26/making-eclipse-plug-ins-using-jruby-or-groovy/
Finding a Class in a ton of jars
Jul 26th
This is how I do it. Create a script I call it findclass in some location on the path. /usr/local/bin is a good place, I prefer $HOME/bin. Remember to chmod this script to 755.
#!/bin/bash
find -iname "*.jar" | xargs -i unzip -l {} | less
In case you are new to less, here’s how you navigate:
1. To find a particular class say com.xyz.abc.MyClass, you type:
/com.xyz.abc.MyClass
2. To find what jar contains this class, you type:
?Archive:
CCTray in Java
May 11th
Akshay and me have been pairing since a couple of days to hack together a java version of CCTray written using SWT. This version of CCTray can connect to CCNET and cc.rb.
A lot of folks use *nix and the existing CCTray is not much help.
If you wish to use this pre-alpha release, feel free to write back. It’s not all that configurable, so you have been warned
Oh, yes, BTW this release depends on issue #899 of CCNet dashboard, and issue #118 of CC.rb. You can vote for these issues to be resolved to see CCTray in Java released a bit earlier.
Kill the mouse, and forget having to remember keyboard shourcuts :)
May 8th
As an Eclipse plug-in developer who’s recently moved to using JetBrains’s IntelliJ Idea; I must agree that IntelliJ has excellent support for having to use the keyboard. I haven’t had to use the mouse much when I’m using IntelliJ.
On the down side — I’ve to remember all the keyboard shortcuts. This is hardly an option when there are a whole lot of keyboard shortcuts to remember, quite a lot keyboard shortcuts in most IDEs don’t really make much sense, and quite a few features do not even have keyboard shortcuts!
NO LONGER!
This Quick Assist (CTRL+3) feature in the latest version (3.3-M7) of eclipse makes available ALL the UI elements – views, menu entries, even refactorings all in one single place. What’s more it supports CamelCaseCompletion. This combination makes for some kick-ass development.
Keyboard Shortcuts — what’s that ?
Oh yeah, and there’s support for a brand new refactoring — Introduce Parameter Object
Composite Logger for Ant
Apr 4th
When doing long builds in CruiseControl, ant build logs are generally logged using the XmlLogger.
In certain cases, say for example when the build is taking longer than usual, and needs to be killed/stopped, the XmlLogger does not flush contents to disk.
It would be nice if there is some sort of a composite logger than can chain any logger along with the XmlLogger.
I just happened to write one sometime today. This is the source code for a CompositeLogger that logs to a default logger, and the XmlLogger. This needs the environment variable ANT_LOG_PREFIX to be set (there’s no better way I can think of)
package com.thoughtworks.ant.logger;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Iterator;
import org.apache.tools.ant.BuildEvent;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.BuildLogger;
import org.apache.tools.ant.DefaultLogger;
import org.apache.tools.ant.XmlLogger;
/**
* @author Ketan Padegaonkar
*/
public class CompositeAntLogger implements BuildLogger {
private ArrayList loggers;
private String logPrefix;
private PrintStream out;
public CompositeAntLogger() {
checkLogPrefix();
createLoggers();
}
public void setEmacsMode(boolean emacsMode) {
for (Iterator iterator = loggers.iterator(); iterator.hasNext();) {
BuildLogger logger = (BuildLogger) iterator.next();
logger.setEmacsMode(emacsMode);
}
}
public void buildFinished(BuildEvent event) {
for (Iterator iterator = loggers.iterator(); iterator.hasNext();) {
BuildLogger logger = (BuildLogger) iterator.next();
logger.buildFinished(event);
}
}
public void buildStarted(BuildEvent event) {
for (Iterator iterator = loggers.iterator(); iterator.hasNext();) {
BuildLogger logger = (BuildLogger) iterator.next();
logger.buildStarted(event);
}
}
public void messageLogged(BuildEvent event) {
for (Iterator iterator = loggers.iterator(); iterator.hasNext();) {
BuildLogger logger = (BuildLogger) iterator.next();
logger.messageLogged(event);
}
}
public void targetFinished(BuildEvent event) {
for (Iterator iterator = loggers.iterator(); iterator.hasNext();) {
BuildLogger logger = (BuildLogger) iterator.next();
logger.targetFinished(event);
}
}
public void targetStarted(BuildEvent event) {
for (Iterator iterator = loggers.iterator(); iterator.hasNext();) {
BuildLogger logger = (BuildLogger) iterator.next();
logger.targetStarted(event);
}
}
public void taskFinished(BuildEvent event) {
for (Iterator iterator = loggers.iterator(); iterator.hasNext();) {
BuildLogger logger = (BuildLogger) iterator.next();
logger.taskFinished(event);
}
}
public void taskStarted(BuildEvent event) {
for (Iterator iterator = loggers.iterator(); iterator.hasNext();) {
BuildLogger logger = (BuildLogger) iterator.next();
logger.taskStarted(event);
}
}
public void setMessageOutputLevel(int level) {
for (Iterator iterator = loggers.iterator(); iterator.hasNext();) {
BuildLogger logger = (BuildLogger) iterator.next();
logger.setMessageOutputLevel(level);
}
}
public void setOutputPrintStream(PrintStream output) {
// do nothing
}
public void setErrorPrintStream(PrintStream err) {
// do nothing
}
private void createLoggers() {
loggers = new ArrayList();
try {
loggers.add(createDefaultLogger());
loggers.add(createXmlLogger());
} catch (FileNotFoundException e) {
throw new BuildException("The loggers could not open the file", e);
}
}
private void checkLogPrefix() {
logPrefix = System.getenv("ANT_LOG_PREFIX");
if (logPrefix == null || logPrefix.trim().length() == 0)
throw new BuildException("You need to set the environment variable ANT_LOG_PREFIX.");
}
private DefaultLogger createDefaultLogger() throws FileNotFoundException {
DefaultLogger logger = new DefaultLogger();
out = new PrintStream(new FileOutputStream(logPrefix + ".txt"));
logger.setOutputPrintStream(out);
logger.setErrorPrintStream(out);
return logger;
}
private XmlLogger createXmlLogger() throws FileNotFoundException {
XmlLogger logger = new XmlLogger();
out = new PrintStream(new FileOutputStream(logPrefix + ".xml"));
logger.setOutputPrintStream(out);
logger.setErrorPrintStream(out);
return logger;
}
}
Lotus Notes beta 8, and Eclipse
Mar 23rd
I saw this post by ZX on Lotus Notes 8 based on the Eclipse platform.
ZX says:
…
In the end, this is great news for Eclipse which now gets to interact with a whole new set of users and developers.Eclipse (OSGi) on clients… devices… servers… , what’s next?
…
OSGi is great on my desktop, laptop, servers, even mobile phones. But lotus notes based on OSGi ? I’m a die hard Eclipse fan and developer. But when it comes to usability of the software that I have to use everyday I’m a tough guy to convince.
For another potshot at this installer (for now) it is about 673 MB, is packaged as a .tar (Anyone at IBM lotus notes packaging team heard about something called as gzip/bzip2?) The documentation (which is about a total of 3MB) comes as a separate download. While it is a good idea to package the documentation separately I wonder if the installer comes with some documentation.
I just hope that I do not have to go through all these pains and musings and some more pains to install Lotus Notes 8. Especially after downloading something that is 673 MB.

