Ski Hard Update

Ski Hard 1.0.13 has just been released to the Google Play store and PC.

Some of the updates are:

  • Resizable window (PC)
  • Match device’s aspect ratio (Android)
  • Press Escape from title screen to quit (PC)
  • Fixing the semi-transparent background on pause and game over screens (PC)
  • In addition to F11, press ALT+Enter to toggle full screen (PC)
  • Google Analytics tracking (Android)
  • Removed test code for generating thumbnail (Android)
  • Play select sound when turning sound on (PC, Android)
  • Bigger bounding boxes when selecting buttons (PC, Android)
  • Group buttons so that other objects do not hide them (PC, Android)

Naming Java threads

Naming the threads in a Java application is good practice as the default name given by a default thread pool looks like this: pool-x-thread-y.

Here is a simple implementation of a named thread factory:

public class NamedThreadFactory implements ThreadFactory {

    private final AtomicInteger threadIndex = new AtomicInteger(0);

    private final String name;

    public NamedThreadFactory(String name) {
        this.name = name;
    }

    @Override
    public Thread newThread(Runnable runnable) {
        Thread thread = new Thread(runnable);
        thread.setName(String.format("%s-%d", name, threadIndex.addAndGet(1)));
        return thread;
    }

}

Use it like this:

ExecutorService threadPool = Executors.newFixedThreadPool(
        numberOfThreads, new NamedThreadFactory("MyUsefulThreadName"));

Logging a unique ID for every request using log4j

I wanted to assign a unique ID to web requests in my application so that I could easily differentiate between different requests when looking at my logs.

My log4j conversion pattern (or format) looked like this:

%d{ISO8601} [%t] %p %c - %m%n

Explanation:

  • %d{ISO8601}: Timestamp using log4j’s ISO8601DateFormat
  • %t: Thread name
  • %p: Priority (eg DEBUG, INFO, etc)
  • %c: Category (in my code I’m using the class as category)
  • %m: Message
  • %n: Line break

I added a custom field:

%d{ISO8601} [%t] %p %c %X{requestId} - %m%n

Using my RandomIdGenerator class, I added this interceptor:

@Override
public boolean preHandle(
        HttpServletRequest request,
        HttpServletResponse response, Object handler) {
    String requestId = RandomIdGenerator.base32(4);
    MDC.put("requestId", requestId);
    return true;
}

I now get output like this in my log:

2013-06-21 10:01:49,178 [http-443-4] INFO com.boxjar.web.AuthenticationInterceptor YDXT5PI - User box authenticated successfully.
2013-06-21 10:01:49,182 [http-443-4] DEBUG com.boxjar.logic.DomainService YDXT5PI - Saved changes to contract 154.

I wish everything was this easy!