IntelliJ Idea adds tags when typing ‘t

This was quite annoying, especially since I failed at googling a cure for it.

What happens: whenever you type “'t” in a comment on a Java file in Idea followed by a whitespace, it gets replaced with “<></>“, and whatever you type after that is added as if it were an HTML tag pair.

If you actually pause after typing “'t” (which I don’t know why it’s something I never did until now), you’ll notice IntelliJ’s auto-complete popup telling you what’s going on:

popup

It turns out that “t” is the shortcut for “tag pair”, which might be awesome for HTML coding, but it’s not as nice when you’re writing comments.

To disable that, go to Settings/Editor/Live Templates/, expand the html/xml line, and uncheck t (tag pair). Hit OK, and it’s gone!

Advertisements

After upgrading, Jenkins doesn’t start: org.xml.sax.saxparseexception: premature end of file

I recently upgraded my Jenkins installation using Debian’s package manager, and to my surprise… Jenkins wouldn’t start!

The error logged in /var/log/jenkins/jenkins.log looked like this:

WARNING: Failed startup of context w.{,file:/var/cache/jenkins/war/},/var/cache/jenkins/war
org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Premature end of file.

followed by a Java stack trace. I noticed a suspicious line in that stack trace:

at org.eclipse.jetty.webapp.MetaData.setWebXml(MetaData.java:170)

interesting. It looked like something was wrong with Jenkins’ web.xml, so I checked /var/cache/jenkins/war/WEB-INF/web.xml and, surprise surprise… it was empty!

I unpacked an old jenkins.war that I had, and copied its web.xml over, restarting the service. A-ha! The logged error changed. Unfortunately, it still wouldn’t start, but it made me look for “jenkins corrupted /var/cache” which finally lead me to this bug report.

“Dang!” – I thought – “is that it?”.

Moved the old /var/cache/jenkins away, created a new empty directory, and set user jenkins as its owner:

mv /var/cache/jenkins ~/var-cache-jenkins-back
mkdir /var/cache/jenkins
chown -R jenkins:jenkins /var/cache/jenkins
service jenkins start

sonofa… it worked!

A template to create log4j Logger objects in Eclipse

In my (server) Java apps, I usually use log4j to keep logs. These days, I actually use SLF4J as a proxy for log4j, mostly because the framework I’m using (Vert.x) uses it.

Over the years I’ve tuned my log format to only store the information I care about, and nothing more than that:

<PatternLayout pattern="[%d{HH:mm:ss.SSS}] %p %c{3} - %m%n" />

so I have a timestamp, the log level (%p), the class name with up to 3 levels of package hierarchy (%c{3}), and the new-line-terminated message (%m%n).

A sample line:

[11:39:36.667] TRACE redis.redis_client.RedisDecoder - received new MultiBulkReply

This format requires a Logger object in all classes that need logging, which requires quite a bit of boilerplate code, e.g.:

private static final Logger LOGGER = LoggerFactory
    .getLogger(SlackRouter.class);

You quickly grow tired of typing all of that. But worry not! Eclipse comes to the rescue!

Setup an Eclipse Template

I created a template that does the work for me: now, all I have to do to add a new Logger object is type log, hit Ctrl + space, and select “Insert logger”.

Just like this:

Adding a Logger

Note that typing “log4” instead of “log” only gives you one option, saving 2 precious key strokes! 😛

Here’s how to set it up for your Eclipse.

  1. Open your Eclipse Preferences menu
  2. Type “java editor templates” in the search bar
    uno
  3. Hit the “New” button
  4. Set “log4j” as name (or whatever you want the shortcut to be), add a description, paste this in the “Pattern” field:
    ${:import(org.slf4j.Logger,org.slf4j.LoggerFactory)}
    private static final Logger LOGGER = LoggerFactory.getLogger(${enclosing_type}.class);
    

    and hit “OK”
    tre

  5. That’s it!

    If you’re not using SLF4J, all you need to do is change the import code to include the actual class you use.

Find the most recent file/folder in a folder with Java 8

A simple snippet that shows how Java 8 lambdas can be really nice to replace operations that used to require a lot of boilerplate in earlier versions of Java.

If you want to find the most recent file or subfolder in a folder with Java 8, here’s what you need to do:

Path parentFolder = Paths.get("path", "to", "your", "file");

Optional<File> mostRecentFileOrFolder =
    Arrays
        .stream(parentFolder.toFile().listFiles())
        .max(
            (f1, f2) -> Long.compare(f1.lastModified(),
                f2.lastModified()));

if (mostRecentFolder.isPresent()) {
    File mostRecent = mostRecentFileOrFolder.get();
    System.out.println("most recent is " + mostRecent.getPath());
} else {
    System.out.println("folder is empty!");
}

The very nice thing is that you can take advantage of the flexibility of Java 8 streams to either make the operation parallel (just throw in a parallel() call after Arrays.stream()), or to filter results according to other criteria.

For example, if you’re only interested in one type of child elements (a file or a folder), you could…

// if you're only interested in files...
Optional<File> mostRecentFile =
    Arrays
        .stream(parentFolder.toFile().listFiles())
        .filter(f -> f.isFile())
        .max(
            (f1, f2) -> Long.compare(f1.lastModified(),
                f2.lastModified()));

// if you're interested in folders...
Optional<File> mostRecentFolder =
    Arrays
        .stream(parentFolder.toFile().listFiles())
        .filter(f -> f.isDirectory())
        .max(
            (f1, f2) -> Long.compare(f1.lastModified(),
                f2.lastModified()));

Run JUnit tests in order

JUnit runs test methods in whatever order it wants, which is generally fine as long as all your test methods are independent of each other. This, though, may not be the case when you’re writing integration tests, where you could have a sequence of operations like

login(credentials);
requestProject("foo");
createNewItem("bar");
logout();

in a situation like this, you always want testLogout() to run after testLogin(), and createNewItem() to run after requestProject()!

Yes, you could group everything in a single test method, but it may become huge and very hard to maintain.

Quite surprisingly, JUnit doesn’t have a built-in solution for this. You can run test methods sorted by name using the @FixMethodOrder(MethodSorters.NAME_ASCENDING) tag, but then you need to artificially name your methods so that they appear in the order you want.

I found some alternative solutions in this stackoverflow question, but they require annotating your methods with tags to specify the order in which you want them to run. What I’d like them to do is just run in the same order as they appear in the source code for the test class. Among the answers, I just found this blog post that achieves the same result as I did, only it looks somewhat more complicated (it involves writing/including several classes).

My solution is fairly simple, but there’s 2 warnings:

  1. it uses Javassist, so if you don’t want to add libraries, there’s that
  2. it only works as long as you don’t have test classes that extend other test classes, and you don’t override all @Test-annotated methods in the subclass (I’ve never done that, but I guess as tests get complicated, you may have that); this can be fixed quite easily though, you just need to add the logic for what should come first according to your needs

On with the code!

You can grab the source straight from this pastebin, or copy/paste it from here (I added the MIT License, I think it should be the most permissive.. my intent is to say “do whatever the heck you want with this code”)

/*
 * Copyright (C) <2014> <Michele Bonazza>
 * 
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

/**
 * A test runner that runs tests according to their position in the source file
 * of the test class.
 * 
 * @author Michele Bonazza
 */
public class OrderedTestRunner extends BlockJUnit4ClassRunner {

    /**
     * Creates a new runner
     * 
     * @param clazz
     *            the class being tested
     * @throws InitializationError
     *             if something goes wrong
     */
    public OrderedTestRunner(Class<?> clazz) throws InitializationError {
        super(clazz);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.junit.runners.BlockJUnit4ClassRunner#computeTestMethods()
     */
    @Override
    protected List<FrameworkMethod> computeTestMethods() {
        // get all methods to be tested
        List<FrameworkMethod> toSort = super.computeTestMethods();

        if (toSort.isEmpty())
            return toSort;

        // a map containing <line_number, method>
        final Map<Integer, FrameworkMethod> testMethods = new TreeMap<>();

        // check that all methods here are declared in the same class, we don't
        // deal with test methods from superclasses that haven't been overridden
        Class<?> clazz = getDeclaringClass(toSort);
        if (clazz == null) {
            // fail explicitly
            System.err
                    .println("OrderedTestRunner can only run test classes that"
                            + " don't have test methods inherited from superclasses");
            return Collections.emptyList();
        }

        // use Javassist to figure out line numbers for methods
        ClassPool pool = ClassPool.getDefault();
        try {
            CtClass cc = pool.get(clazz.getName());
            // all methods in toSort are declared in the same class, we checked
            for (FrameworkMethod m : toSort) {
                String methodName = m.getName();
                CtMethod method = cc.getDeclaredMethod(methodName);
                testMethods.put(method.getMethodInfo().getLineNumber(0), m);
            }
        } catch (NotFoundException e) {
            e.printStackTrace();
        }

        return new ArrayList<>(testMethods.values());
    }

    private Class<?> getDeclaringClass(List<FrameworkMethod> methods) {
        // methods can't be empty, it's been checked
        Class<?> clazz = methods.get(0).getMethod().getDeclaringClass();

        for (int i = 1; i < methods.size(); i++) {
            if (!methods.get(i).getMethod().getDeclaringClass().equals(clazz)) {
                // they must be all in the same class
                return null;
            }
        }

        return clazz;
    }
}

to use this, you need to add Javassist to your classpath; if you have a Maven project, it’s incredibly easy to do so, just add this to your POM:

<dependency>
  <groupId>javassist</groupId>
  <artifactId>javassist</artifactId>
  <version>3.12.1.GA</version>
</dependency>

and annotate your JUnit test class with @RunWith(OrderedTestRunner.class), like this:

import wherever.you.put.OrderedTestRunner;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(OrderedTestRunner.class)
public class MyTestClass {

    @Test
    public void testZero() {
        System.out.println("test zero run");
    }

    @Test
    public void testOne() {
        System.out.println("test one run");
    }
}

That’s it!

About warning 2. above, in case you have something like MyTestClass extends BaseTestClass and you have methods annotated with @Test in BaseTestClass that aren’t overridden by MyTestClass, OrderedTestRunner will just fail printing the message you can see at line 50 above on System.err. I did this because I don’t think there’s a well-defined order in that case (should all methods from the super class run first? Should that go all the way up in the class hierarchy?), so you can adjust it to fit your particular needs.

Could not open the requested socket: Address already in use. Restart Jetty from Eclipse on Mac OSX

I am used to hit on the Play button in Eclipse like hell when developing server apps, so I ran into this issue pretty quickly.

When you’re working with Google App Engine on Mac OSX, pressing that familiar green button after having deployed the app once makes Eclipse complain as in the title. The stop button is grayed out (as it’s controlling the latest instance of Jetty, which didn’t start) and you can’t launch your app without restarting Eclipse.

So, to kill the old Jetty instance you just open a terminal and type:

lsof -i TCP:8888 | grep java | grep LISTEN

Where 8888 is the port on which Jetty is listening (it could be 8080 or something else depending on your configuration), and the first grep is just to stay on the safe side (you don’t want to kill something else). If you’re sure that there’s nothing else listening on that port, just omit it.

The output will be something like

java    33873 myusername   68u  IPv6 0xffffff801a2c1510      0t0  TCP localhost:ddi-tcp-1 (LISTEN)

Then, just type

kill -15 33873

where 33873 is the number in the second column in the output of the previous command.

You can then run the project from Eclipse.

My routine is to keep a terminal window open and just run this one-liner when I run into the error:

kill -15 $(lsof -i TCP:8888 | grep java | grep LISTEN | awk '{ print $2 }')

which does exactly the same thing, but in an automated fashion… it’s just an arrow_up away! 🙂

Stack notifications on Android (plus: get users to see your notifications on JellyBean – phone/phablet UI)

This is something I put together for WhatsHare, a small open source app that I published; I couldn’t find a tutorial that had all of this together in one place.

My app (actually, just one particular Activity) has no UI: it receives an Intent, does its thing and finish()es. The only way I found to notify the user that it’s done something is to add a Notification, as dialogs would get too in the way.

I want the notification to be shown every single time, as it must tell the user “ok, I did something” or “an error occurred”, because she has no other way of knowing if the app even worked!

On the other hand, I don’t want to pollute the notification area with lots of “Success!” notifications, as they’re ultimately pointless once the user has seen them.

The options were to either:

  1. automatically cancel() the notification once the message has been displayed, or
  2. show the message every time, but collapse all notifications into a single one, with an increasing counter

I preferred the latter approach, as I think it feels a little more predictable for the user (also, the other solution requires dedicated services/timers, so it’s probably more complicated).

Here’s the final code , comments follow:

@SuppressWarnings("deprecation")
private void showNotification(int sharedWhat) {
    String title = getString(R.string.app_name);
    // this will be routed to onNewIntent(), SendToGCMActivity is this class
    Intent onNotificationDiscarded = new Intent(this,
            SendToGCMActivity.class);
    PendingIntent notificationIntent = PendingIntent.getActivity(this, 0,
            onNotificationDiscarded, 0);
    Notification notification = null;
    String content = getString(R.string.share_success,
            getString(sharedWhat), outboundDevice.type);
    
    // notificationCounter is a private static AtomicInteger
    int notificationNumber = notificationCounter.incrementAndGet();

    NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
            .setSmallIcon(R.drawable.notification_icon, 0)
            .setContentTitle(title)
            .setContentText(content)
            .setTicker(content)
            .setContentIntent(notificationIntent)
            .setDeleteIntent(PendingIntent.getActivity(this, 0, onNotificationDiscarded, 0))
            // update the counter
            .setNumber(notificationNumber);

    if (Build.VERSION.SDK_INT > 15) {
        notification = buildForJellyBean(builder);
    } else {
        notification = builder.getNotification();
    }

    // notifications disappear after the user taps on them
    notification.flags |= Notification.FLAG_AUTO_CANCEL;
    NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

    // cancel previous notification to clean up garbage in the status bar
    nm.cancel(notificationNumber - 1);
    // add new notification
    nm.notify(notificationNumber, notification);
}

@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
private Notification buildForJellyBean(NotificationCompat.Builder builder) {
    // for some reason Notification.PRIORITY_DEFAULT doesn't show the counter
    builder.setPriority(Notification.PRIORITY_HIGH);
    return builder.build();
}

protected void onNewIntent(final Intent intent) {
    if (intent.hasExtra(Intent.EXTRA_TEXT)) {
        // do your thing
        // ...code goes here
        showNotification(R.string.link);
    } else {
        // user clicked on the notification
        notificationCounter.set(0);
    }
    // this is needed cause even if we set android:theme="@android:style/Theme.NoDisplay"
    // an invisible overlay is laid out on top of the caller activity, we don't want that
    finish();
}

It works like this:

  • you define a static counter for all your notifications, so that the NotificationManager treats them as separate
  • AUTO_CANCEL is set so when the user taps on the notification it disappears
  • setDeleteIntent() is called to have an Intent routed to the Activity’s onNewIntent() method whenever the notification is discarded, so we can reset the counter. If users tap on the notification, onNewIntent() is also called because of notificationIntent being set as content intent
  • since this activity has an intent-filter for action.SEND of type text/plain, we know that an Intent with no EXTRA_TEXT field can only be passed explicitly — that is, by setting the class target when creating the Intent –. We could add some other extra if we wanted to make extra sure that the Intent comes from that specific class
  • whenever a notification needs to be stacked, we cancel() the previous one (using its id, which is always the current counter minus one) and create a new one with the updated count

That’s the magic behind stacked notifications: Android does not show your notifications if you’re just updating them, so you need to cancel the old one and add the new one. If you don’t need to show the message every time, just update the previous notification using its id (that must not change, so no counter at all).

About JellyBean: if you don’t raise the notification’s priority to at least PRIORITY_HIGH it won’t show the counter on phones/phablets for some reason. Also, to make sure that messages are displayed every time on phone/phablets you must set them as tickers; tablets instead show the full message set by setContentText() anyway.

A final note: I’m using NotificationCompat.Builder instead of plain Notification.Builder to support older devices. You can find that class in the support library (android.support.v4.app package). If you’re targeting honeycomb and higher, just use Notification.Builder.