Archive for the ‘java’ Category

How I Learned to Stop Worrying about Serialization and Love the Wrapper

Saturday, June 18th, 2011 by viktor

Background
One of the great benefits with Firebase is the support for transparent failover. All you as a game developer have to do is to make sure that your game state is serializable.

The Problem
One common pattern that follows from this approach is that non-serializable classes (such as the Notifier or the Scheduler) tend to get passed around a whole lot, because they can’t be stored as instance variables. If you want to do Domain Driven Development, this is a bad pattern.

Half of the Solution
Storing those instances as “transient” is always an option, but only solves half of the problem. On deserialization, those values will be null and there’s no way to recreate them in readObject().

The Solution
Instead of referring to the Scheduler and Notifier directly, create a wrapper class which holds them as transient members. Then, pass that into all your collaborating classes. The parent class will hold a reference to this same wrapper and on each call from Firebase, it will inject the live versions of the Notifier and Scheduler and since all collaborating classes refer to the same instance of the wrapper, we’re now all set!

An Example
I find that a concrete example always makes things clearer. Here’s some code for a poker game. First, here’s the game state class.

public class Poker implements Serializable {
    private Wrapper wrapper = new Wrapper();

    public void addPlayer() {
        Player player = new Player(wrapper);
        ...
    }

    public void handle(GameDataAction action, Table table) {
        injectCallbacks(table.getNotifier(), table.getScheduler());
        ...
    }

    private void injectCallbacks(GameNotifier notifier, Scheduler scheduler) {
        wrapper.setNotifier(notifier);
        wrapper.setScheduler(scheduler);
    }
}

And here’s the wrapper.

public class Wrapper implements Serializable {
    private transient GameNotifer notifier;
    private transient Scheduler scheduler;

    ... getters and setters ...
}

Which means that from any any place in the code, we can do something like player.updateBalance(newBalance), which would look like:

public void updateBalance(int newBalance) {
    balance = newBalance;
    getNotifier().notifyAllPlayers(createGameDataAction(newBalance));
}

So, time for you to fire up your refactoring tool and put some candy in that wrapper!

Unit Tests with Guice and Warp Persist

Sunday, April 25th, 2010 by larsan

Yesterday I needed to do some unit testing for a project using Guice and Warp Persist. And one thing that seems to be lacking, or wasn’t to be found be me yesterday, is the kind of unit testing you can do with Spring, where each method is wrapped by a transaction which is rolled back when the method ends.

To simplify, it enables you to do this:

@Test
public void createUser() {
    User u = userService.createUserWithId(1);
}

@Test
public void createUserWithSameId() {
    User u = userService.createUserWithId(1);
}

If you assume the “userService” is transactional, we’re on a database that spans multiple methods, and that the user ID must be unique, the above pseudo-code should fail as we’re trying to create two users with the same ID. If, however, there was a transaction wrapping both methods, and that transaction was rolled back, we’d be fine.

So, can you do it with Guice and Warp Persist? Sure you can!

(I’m using TestNG and JPA by the way, but you’ll get the point).

We’ll create a base class that sets up the Guice context as well as handles the transactions for us. Let’s start with creating the methods we need:

public abstract class JpaTestBase {

  @BeforeClass
  public void setUpJpa() throws Exception {
    // setup guice + jpa here here
  }

  @AfterClass
  public void tearDownJpa() throws Exception {
    // stop jpa here
  }

  /**
   * Return the module needed for the test.
   */
  protected abstract List<? extends Module> testModules();

  @BeforeMethod
  public void setupTransaction() throws Exception {
    // create "session in view"
  }

  @AfterMethod
  public void cleanTransaction() throws Exception {
    // rollback transaction and close session
  }
}

We’re using the TestNG “before” and “after” class to setup and tear down JPA. If the test was in a bigger suite you could probably do it around all test classes, but this will do for now. I’m also including a “testModules” method that subclasses should use to make sure their own test classes are setup correctly.

Before we go on, I’ll add some dependencies which will be explained later:

@Inject
protected PersistenceService service;

@Inject
protected WorkManager workManager;

@Inject
protected Provider<EntityManagerFactory> emfProvider;

We’ll setup the Guice context and the JPA persistence service in the “setUpJpa” method:

@BeforeClass
public void setUpJpa() throws Exception {
  // create list with subclass modules
  List<Module> list = new LinkedList<Module>(testModules());

  // add persistence module
  list.add(PersistenceService
            .usingJpa()
            .across(UnitOfWork.REQUEST)
            .forAll(Matchers.annotatedWith(Transactional.class), Matchers.any())
            .buildModule());

  // modules to array and create Guice
  Module[] arr = list.toArray(new Module[list.size()]);
  injector = Guice.createInjector(arr);

  // make sure we get our dependencies
  injector.injectMembers(this);

  // NB: we need to start the service (injected)
  service.start();
}

The persistence service will work across UnitOfWork.REQUEST as that’s what we’re emulating here. I’m also matching the transaction for any classes, this enables me to mark an entire class as transactional, as opposed to single methods, which I find handy.

All we need to do to shut down is to close the service, like so:

@AfterClass
public void tearDownJpa() throws Exception {
  service.shutdown();
}

Now, let’s wrap the methods. Remember our dependency injections earlier? Well, here’s where they come in handy. The WorkManager is used by Warp Persist to manage a session, we can tell it to start and end “work” and this will correspond to an EntityManager bound to the current thread. Let’s start with that:

@BeforeMethod
public void setupTransaction() throws Exception {
  workManager.beginWork();
}

@AfterMethod
public void cleanTransaction() throws Exception {
  workManager.endWork();
}

So before each method we’ll open a new EntityManager which will be closed when the method ends. So far so good. Now, in order to enable a rollback when the method ends we first need to wrap the entire execution in a transaction, which means we need to get hold of the EntityManager. Luckily, Warp Persist has a class called ManagedContext which holds currently bound objects (a bit like a custom scope), in which we’ll find our EntityManager keyed to it’s persistence context, ie. the EntityManagerFactory that created it. Take a look again at the injected dependencies we injected above: As the test only handles one persistence context we can safely let Guice inject a Provider for an EntityManagerFactory for us and assume it is going to be the right one.

Still with me? OK, let’s do it then:

@BeforeMethod
public void setupTransaction() throws Exception {
  // begin work
  workManager.beginWork();
  // get the entity manager, using it's factory
  EntityManagerFactory emf = emfProvider.get();
  EntityManager man = ManagedContext.getBind(EntityManager.class, emf);
  // begin transaction
  man.getTransaction().begin();
}

@AfterMethod
public void cleanTransaction() throws Exception {
  // get the entity manager, using its factory
  EntityManagerFactory emf = emfProvider.get();
  EntityManager man = ManagedContext.getBind(EntityManager.class, emf);
  // rollback transaction
  man.getTransaction().rollback();
  // end work
  workManager.endWork();
}

And that’s it! Each test method is now within a transaction that will be rolled back when the method ends. Now all you need to do is to write the actual tests…

A Google Analytics Plugin for Nexus

Thursday, February 11th, 2010 by larsan

Since Firebase Community Edition uses Maven heavily, I realized I’d like to track our Nexus repository in Google Analytics. The Nexus Book says that there exists such a plugin already, but apparently now one knows where it is. So here’s my attempt to write a simple one.

If you’re an impatient kind, here’s the source code.

I created the project  in Eclipse, instructions here.

Now, let’s start off with a “repository customizer” which is Nexus extension point we’ll use to insert a custom request processor into every repository…

public class GaTrackerRepositoryCustomizer implements RepositoryCustomizer {

    private final Logger log = LoggerFactory.getLogger(getClass());

    @Inject
    @Named("gaTracker")
    private RequestProcessor gaTracker;

    @Override
    public void configureRepository(Repository rep) throws ConfigurationException {
        log.debug("Attaching tracker to: " + rep.getName());
        rep.getRequestProcessors().put("gaTracker", gaTracker);
    }

    @Override
    public boolean isHandledRepository(Repository rep) {
        boolean b = true;
        log.info("Handles repository '" + rep.getName() + "': " + b);
        return b;
    }
}

Not too complicated. We’re using injection to get hold of the actual tracker components and we’re inserting it into all repostories.

Wait, all repositories? Yes, and it’s problem I haven’t really figured out yet. Ideally I’d like to track “hosted” repositories only. However, we’ve configured all our builds to use a few common development “groups” for convenience. However, Nexus seems to treat groups as first class members, so even though an artifact may be deployed in a hosted repository while accessed through a group, the request processor will not get notified for the hosted repository, only the group. I tend to see “groups” as equivalent to “views” in which case I’d expect the hosted repository to be called as well, but, no…

Now, let’s create a request processor which will react when someone “reads” a path in a repository.  We’ll take it in pieces…

@Named("gaTracker")
public class GaTrackerRequestProcessor implements RequestProcessor {

    public static final String GA_TRACKER_ID =
        System.getProperty("cubeia.nexus.gaTrackerId");
    public static final String GA_REFERER_URL =
        System.getProperty("cubeia.nexus.gaRefererUrl");

    private final Logger log = LoggerFactory.getLogger(getClass());
    private final JGoogleAnalyticsTracker tracker;

    public GaTrackerRequestProcessor() {
        if(GA_TRACKER_ID == null) {
            String msg = "Missing system property 'cubeia.nexus.gaTrackerId'";
            throw new IllegalStateException(msg);
        }
         log.info("Creating new tracker, with id: " + GA_TRACKER_ID);
        tracker = new JGoogleAnalyticsTracker("nexus", "read", GA_TRACKER_ID);
        checkRefererUrl();
        adaptLogging();
    }

    [...]

We configure the plugin via system properties (not too beautiful, I know), the “tracker id” is the google tracking code id and is mandatory, and the “refer url” will be set on the call to GA if available.  We’re using the JGoogleAnalytics library to call GA for us. Also, I’m being naughty and throwing an illegal state exception if the tracker id is missing, since GA updates every 24 hours we’d like to be notified on errors early.

There’s  two methods above, one sets the logging in the tracker code to use to slf4j logger instead and the other checks for and sets the referer URL:

private void adaptLogging() {
    /*
     * Adapt the logging to use slf4j instead.
     */
    tracker.setLoggingAdapter(new LoggingAdapter() {

        public void logMessage(String msg) {
            log.debug(msg);
        }

        public void logError(String msg) {
            log.error(msg);
        }
    });
}

private void checkRefererUrl() {
    if(GA_REFERER_URL != null) {
        /*
         * If we have a referer URL we need to set this. However, the
         * tracker does not have a getter for the URL binding strategy, so
         * we'll simply create a new one, ugly, but works.
         */
        log.info("Modifying GA tracking to use referer URL: " + GA_REFERER_URL);
        GoogleAnalytics_v1_URLBuildingStrategy urlb;
        urlb = new GoogleAnalytics_v1_URLBuildingStrategy("nexus", "read", GA_TRACKER_ID);
        urlb.setRefererURL("http://m2.cubeia.com");
        // set new referer
        tracker.setUrlBuildingStrategy(urlb);
    }
}

Not too complicated eh? The only thing to note is that the only way to set the refer URL isby creating a new URL building strategy. Well, I can live with that.

Before we go on we’ll create a small subclass on FocusPoint which we’ll use for tracking. Since JGoogleAnalitycs is made primarily for applications the focus point will URL encode itself, however, that won’t work for us, so we need to override it’s getContentURI method:

/**
 * Simple inner class that adapts the content URI to
 * not be URL-escaped.
 */
private static class Point extends FocusPoint {

    public Point(String name) {
        super(name);
    }

    @Override
    public String getContentURI() {
        return getName();
    }
}

And finally we’ll tie it all toghether. We’ll react on “read” actions, create a URI (of form ‘//path’) and track asynchronously (which will spawn a new thread for calling GA:

 public boolean process(Repository rep, ResourceStoreRequest req, Action action) {
    if(action == Action.read) {
        /*
         * 1) create path by appending repo path to repo id
         * 2) create a subclass of focus point that handles proper URI's
         * 3) track asynchronously, this will perform the tracking on a new thread
         */
        String path = rep.getId() + req.getRequestPath();
        log.debug("Tracking path: " + path);
        FocusPoint p = new Point(path);
        tracker.trackAsynchronously(p);
    } else {
        log.debug("Ingoring action '" + action + "' for: " + req.getRequestPath());
    }
    return true;
}

And that’s it. It’s not perfect though ideally I’d like to track hosted repositories only, I’d like to avoid tracking crawlers and I would prefer not to configure via system properties (hint for you Nexus bundle users out there, you can set system properties in the “conf/wrapper.conf” files), but I’ll leave those for a rainy day.

Here’s the source code as a Maven project.

Enjoy!

Update: If you download and try to compile, you will probably be missing the JGoogleAnalytics lib. You’re welcome to use our, GA-tracked, repository if you like :-)

<repository>
  <id>cubeia-nexus</id>
  <url>http://m2.cubeia.com/nexus/content/groups/public/</url>
  <releases>
    <enabled>true</enabled>
  </releases>
  <snapshots>
    <enabled>true</enabled>
  </snapshots>
</repository>

Pomodoro client

Saturday, May 30th, 2009 by fredrik

Viktor and I have released a small client application for working with the Pomodoro technique.

What is Pomodoro?

The aim of the Pomodoro Technique is to use time as a valuable ally in accomplishing what we want to do in the way we want to do it, and to enable us to continually improve the way we work or study.

The application is called Pomodairo and is released as open source at Google Code. You can find the application here.

There is also a good and free book about the Pomodoro technique here.

A Java Concurrency Bug, and How We Solved It

Tuesday, April 14th, 2009 by larsan

Everyone agrees that good debugging is critical. But it is not entirely trivial when it comes to multi-threaded applications. Here’s the story how I tracked down a nasty bug in the Java5 ReentrantReadWriteLock.

Update 15/4: To be a bit clearer, the Java bug in question is on 1) Java 5; and 2) only when using fair locks, non fairness seems to work, however, that was never an option for us, if nothing else due to this other Java bug… Thanks to Artur Biesiadowski for the heads up.

Our product Firebase is designed to offload threading issues and scalability from game developers to a generic platform. However, one of our customers experienced mysterious “freezes” when running a fairly small system load in their staging environment.

First step on the way: getting stack dumps when the system is frozen. In other words, request that the client do a “kill -3” on the server process when it’s hanged, as this dumps all threads and their current stack traces to the standard output. This we did, but only got confused by it, all threads seemed dormant and there was no visible dead-lock in the stack traces.

However, several threads were all mysteriously waiting on a read lock deep down in the server, and seemingly not getting any further, despite that fact that no-one was holding the write lock. This wasn’t conclusive though as there was one thread waiting to take the write lock and this would block the readers. But given that the server was actually frozen it looked suspicious. So my first analysis concluded:

As far as I can see, the only abnormal thing that could have caused this stack is if a thread have taken the lock (read or write) and then crashed without releasing it, however there doesn’t seem to be any place in the code not safeguarded by try/finally (where the lock is released in the finally clause).

Implied in that conclusion is of course that this might either be a normal behavior and we’re looking in the wrong direction, or that we have a more serious Java error on our hands.

There’s a lot of information to be had from a ReentrantReadWriteLock, including the threads waiting for either read or write privileges, and the thread holding a write lock (if any), but not (strangely enough) the threads actually holding a read lock. And as a reader thread can effectively block the entire lock by not unlocking while a writer is waiting, this is information you really need to know.

So the next step was to get hold of the reader threads. I did this by sub-classing the ReentrantReadWriteLock to return my own version of the read lock, which, simplified, did this:

Set readers = Collections.synchronizedSet(new HashSet());  

public Set getReaders() {
    return readers;
}  

public void lock() {
    super.lock();
    readers.add(Thread.currentThread());
}  

public void unlock() {
    super.unlock();
    readers.remove(Thread.currentThread());
}

Given this code, we now have a set containing a snapshot of the threads holding the read lock. I then added a JMX command for printing the following information to standard out for the given read/write lock:

  1. The threads waiting for a read lock, including their stack traces.

  2. The threads waiting for the write lock, including their stack traces.

  3. Any threads holding a read lock, including their stack traces.

  4. The thread holding the write lock, including its stack trace, if any.

I shipped this patched code to the client and asked them to freeze the server with the patch, print the new debug information, and then send me the output. Which they did, and the relevant output looked like this (very much shortened):

Holding reader: Thread[DQueue Handoff Executor Pool Thread { GAME }-1,5,main]
    sun.misc.Unsafe.park(Native Method)
    java.util.concurrent.locks.LockSupport.park(LockSupport.java:118)
    […]  

Waiting writer: Thread[Incoming,dqueue,127.0.0.1:7801,5,Thread Pools]
    sun.misc.Unsafe.park(Native Method)
    […]  

Waiting reader: Thread[DQueue Handoff Executor Pool Thread { GAME }-1,5,main]
    sun.misc.Unsafe.park(Native Method)
    [...]

See anything strange here? It appears that the same thread is both holding and waiting for a read lock at the same time. But this is supposed to be a reentrant lock. In which case…

So, the freeze was caused by this: There’s a bug in Java5 (but not in Java6) where a fair ReentrantReadWriteLock stops a reader from re-entering the lock if there’s a writer waiting. It is of course easy to write a test case for, which you can find here.

This is now submitted as a bug to Sun, but I have yet to get a confirmation and bug number.

As for Firebase, it is now patched and released to use manually tracked re-entrance for read/write locks through the entire server when running under Java5, looking, again very much simplified, like this:

private ThreadLocal count = new ThreadLocal();  

public void lock() {
    if (get() == 0) {
        // don't lock if we alread have a count, in other words, only
        // really lock the first time we enter the lock
        super.lock();
    }
    // increment counter
    increment();
}  

public void unlock() {
    if (get() == 0) {
        // we don't have the lock, this is an illegal state
        throw new IllegalMonitorStateException();
    } else if (get() == 1) {
        // we have the lock, and this is the “first” one, so unlock
        super.unlock();
        remove();
    } else {
        // this is not the “first” lock, so just count down
        decrement();
    }
}	

// --- HELPER METHODS --- //  

private void remove() {
    count.remove();
} 	 

private int get() {
    AtomicInteger i = count.get();
    if (i == null) return 0;
    else {
        return i.intValue();
    }
} 	 

private void increment() {
    AtomicInteger i = count.get();
    if (i == null) {
        i = new AtomicInteger(0);
        count.set(i);
    }
    i.incrementAndGet();
} 	 

private void decrement() {
    AtomicInteger i = count.get();
    if (i == null) {
        // we should never get here...
        throw new IllegalStateException();
    }
    i.decrementAndGet();
}

The above code isn’t trivial, but shouldn’t be too hard to decode: We’re simple managing a “count” each time a thread takes the read lock, but we’re only actually locking the first time, the other times we simply increment the counter. On unlock, we decrement the counter, and if it is the “last” lock, if the counter equals 1, we do the real unlock and remove the counter.

There are two things to learn, 1) in any sufficiently complex server, the above debug information is nice to have from the start on any important lock; and 2) it really is time to migrate to Java6.

Lars J. Nilsson is a founder and Executive Vice President of Cubeia Ltd. He’s an autodidact programmer, former opera singer, and lunch time poet. You can contact him at lars.j.nilsson in Cubeia’s domain.

New Article: Real Time BI

Tuesday, March 10th, 2009 by larsan

Since I’ve spent some time discussing complex event processing in various contexts the last weeks, I thought I’d write up a small article about it. And lo, here it is.

I do point out in the beginning that the article is primarily targeted towards gambling networks, however it can be applied to other domains as well. Financial fraud management? Sure. Industry process supervision? No problems. And so on…

Class Loading and AOP

Wednesday, February 25th, 2009 by larsan

I have a new article up, Debugging Class Loading with AOP, in which I briefly discuss how Aspect Oriented Programming (AOP) using AspectJ can be used to debug class loading, in particular in instances where a system have multiple class loaders.

It does not cover how to use the load time weaver that comes with AspectJ. For you reference, this is roughly how to use it (for Java 5 or higher):

  1. Download AspectJ from the Eclipse site.
  2. Create a configuration file called “aop.xml” in a META-INF folder on the class path. For an example file, see below.
  3. Start your VM with: -javaagent:pathto/aspectjweaver.jar

Which is about it, the “aop.xml” file may look something like this for running the code in the article in a Tomcat 6 installation:

<code lost in blog system move>

Notice above that we include the base package of your application for weaving and the Catalina class loader packages. We’re doing this to limit the scope of the weaver, otherwise your debugging may take a bit too much time and resources.

How to Solve the “file already exists” Maven/SVN Problem

Friday, February 20th, 2009 by viktor

If you are using Subversion and Maven, you might have experienced a message that looks something like: svn: File ‘/folder/pom.xml’ already exists, when executing the “mvn release:prepare” goal.

This has surely caused some frustration for us. After looking around we understood that the underlying bug is in Subversion while the Maven problem is reported here.

In the latter bug report, there is a suggestion for a workaround:

First, execute “mvn release:prepare”. When the error message appears, run “svn update” and then try again with “mvn release:prepare -Dresume”.

This has worked every time for us, but it has not ceased to feel like an ugly workaround.

Good luck!

Design a Server Cluster for Load Testing

Saturday, February 14th, 2009 by fredrik

I have composed a new article which describes how we implemented a clustered solution on top of an existing load generator in Java. The article can be found here: How to Design a Server Cluster for Load Testing

10 Sure Signs You Are Doing Maven Wrong

Friday, February 13th, 2009 by viktor

The “Maven Frustration Syndrome” is a severe decease that I don’t think many developers using Maven have not suffered from. Luckily, there are ways to rub Maven the right way. Here’s a list of ten things that I have seen in many projects and what to do about them. The best part of it all is that there are pretty quick fixes to most of these issues.

1. You constantly update and “mvn install” everything and the kitchen sink, just to be sure

This is the most common problem I have seen. The fix for this will have benefits for many of the points below. Here’s a statement that I don’t think you can find anywhere in the Maven documentation, but that I firmly believe is true:
“Every Maven artifact HAS to have a home in one Maven repository.”

This means that, in your company, you have to have a repository manager, such as Archiva or Artifactory. Every module that you develop must be deployed to this repository. When should we deploy our artifacts, you might ask? The answer is: after each successful build, by your build server. We currently use Hudson for this, but Continuum or TeamCity will do the job as well.

Now, when each module is always deployed to the repository, and your Maven installation fetches its dependencies from this repository, you will no longer have to “update and install everything”. If you are working on one module, you should only have to build that module. The other modules will be downloaded to you automatically.

2. You and your colleagues solve the “dependency not found” problem by copying someone’s entire .m2-folder via memory stick
As crazy as this workaround seems, I have seen it done over and over again. Again, the solution is to have a repository manager. Once this is hooked up properly, you will never have to do the ugly “who has a memory stick?” dance again. You shouldn’t even have to fear wiping your local repository entirely, since download speed from the local repository manager should be very fast.

3. You solve missing dependency problems to old versions of local artifacts by taking the latest pom file of the module, changing the version and then installing that module
Consider the scenario where someone has changed the version of a module from 1.3-SNAPSHOT to 1.4-SNAPSHOT. You have been on a (well deserved) holiday, so you never updated and installed the 1.3-SNAPSHOT. Now, there’s another module that depends on 1.3-SNAPSHOT. How will you get a hold of that version? Well, you could dig around in the source management system to find the latest version of the module, where the version was still 1.3-SNAPSHOT, update to that version and install it. Or you could do the dirty trick of just changing your latest checkout from 1.4 to 1.3, install and then cross your fingers and hope that it works.

I think we all can agree that neither solution is pretty. Again, had your company had a repository manager, if there were at least one successful build of 1.3-SNAPSHOT, it would be in the repository. Problem solved.

4. You have lots of shell scripts / batch files that traverse the target folders of your modules to create a zip file
Maven has a way of doing this, called “assemblies”. They are not the easiest to set up, but once you have it set up, it will integrate with Maven in a much smoother way than most home cooked scripts. There are so many things that can go wrong with these scripts once versions start to change, modules are moved and so on. I think this is a matter of using the tool that is designed to do the job. This also means that you can create an assembly and deploy it to the Maven repository. Indeed, this is how we publish the distributions of Firebase to our customers and it works well for us.

5. You have lots of xml in your poms whose only purpose is to copy files into your deploy folders, but it’s not working properly and it’s not portable
This is the flip side of the coin in point 4. Maven does not seem to be built for copying files. If all you want to do is to copy your artifact (be it a war, an ear or a zip file), it might be easier to just create an ant / shell / batch script to do the job. I have been known to be a culprit of trying to bend Maven this way, but it just doesn’t seem to want to go there with me. One issue is which phase to bind the copy task to, not to mention problems with making the solution portable, so that your colleague can have the file copied to C:deploy, you can have it deployed to ~/deploy while the build server should skip this step altogether.

6. Your build stalls forever on “checking for updates from xxx-repo” and you don’t know why
This is a real time consumer that few developers seem to be sufficiently annoyed by to find the root cause of. Perhaps the delay is just too good of an excuse to go and get a coffee. Anyhow, a common cause of this problem is that you have snapshot dependencies and a number of repositories listed in your pom files. Maven has no concept of which artifact it should check for in which repository, so it happily looks for updates of all artifacts in all repositories. The trick, again (you guessed it), is to use a repository manager.

If you configure your Maven installation to look for all artifacts in this repository (by setting a mirror in your settings.xml), Maven will only look there. Since this server is local, it will be fast. It’s important here that the repository manager is also configured properly. For Archiva, this means that you should cache failures and only update snapshots daily.

7. If you work on the release branch, your trunk build might fail (or 1.0-SNAPSHOT should be good enough for everyone)
There are a few things that you should remember to do when creating a branch of your project. One is to tell your build server to also build this branch and the other is to change the version in your pom files. If you neglect to do the latter, problems will ensue when you change the signature of a method in your branch, and then try to develop on the trunk again.

There is a goal in the release plugin called “branch“, by running “mvn release:branch”, Maven can automatically rename the versions in the poms for you. (Disclaimer, I haven’t tried this myself, since we usually only branch when we create a release, using “mvn release:prepare” followed by “mvn release:perform”).

8. All your company internal dependencies end with -SNAPSHOT
The idea of a snapshot seems comforting to developers. It’s almost done. But sooner or later, you will have to put your foot down and release your module to the world, or at least your colleagues. There are a few problems with staying in snapshot land forever. First, it slows down your build, since Maven has to check for the latest snapshot from remote repositories (or at least repository, if you followed point 6). Second, if you depend on a snapshot, it’s hard to know which version of the snapshot you are depending on. My build can fail, while your build works, just because you happen to have a newer snapshot.

If you depend on a company internal module that works the way it is right now, it might be a good idea to drop a release of that module and change the dependency to the non snapshot version. Now we know that even if the guys working on that module go crazy with new features, your module will still build, since it depends on a stable release.

9. If you run “mvn dependency:analyze” the list of unused and undeclared dependencies is too long to recite before lunch
This might seem a bit anal, but there is a real danger in not knowing exactly what you depend on. The biggest issue here is caused by a problem with Maven’s way of handling transitive dependencies. Because of this, you can use code in your dependency’s dependencies and it will compile just fine. The problems come when either you decide to change the scope of that dependency to “provided”, or the writers of the module you depend on decide to change its dependencies. Now, the code will no longer compile. It also is an undocumented dependency which can lure you into a false sense of security. I have written more about this issue here.

Luckily, there is a way to check how many shortcuts you have taken by running “mvn dependency:analyze”. This will tell you which modules you are using without having declared a dependency to them and which modules you depend on, but are not using. Obviously, the second list is not as dangerous, but still brings in unnecessary jar files which will increase build time and the size of your project assemblies.

10. When someone releases a new version of a plugin that you use, your builds tend to fail
Maven has for some reason decided that you don’t need to specify the version of your plugin dependencies. Maven will find the “latest and greatest” for you. When a new version of a plugin is released, you will download and use it without knowing it. Sometimes, the “latest and greatest” is not always so, as low and behold, new versions can contain new bugs. Therefore, it is a good practice to always declare the version that you wish to use when you specify a plugin in your pom file. If you really want to be sure, you can specify the versions of Maven’s internal plugins as well.

References
The Official Maven Site
Maven: The Definitive Guide