Uncategorized

fb-android-dagger 1.0.5 released

Just a quick note for you fb-android-dagger users out there... I just released a new version of fb-android-dagger.  Pretty minor update, but a few things to note:

  1. I've updated the dagger dependency in the POM to version 1.2.1 (the latest).  There's a 2.0 version of dagger coming out at some point, but for now, this is what we've got.
  2. The POM file dependencies on the Android SDK and the Support v4 library have been updated to the latest versions.  I also switched over to using the groupId/artifactId/version values created by the Maven Android SDK Deployer, rather than the ones from Maven Central (which are unofficial and outdated).
  3. Misc other minor POM file updates.
  4. Thanks to a contribution from Tobias Preuss, the dependency on Guava has been removed.

Get it from Github or from Maven Central using:

<dependency>
   <groupId>com.fizz-buzz</groupId>
   <artifactId>fb-android-dagger</artifactId>
   <version>1.0.5</version>
</dependency>

Speed up YouTube videos by 33-50%

I watch a lot of lengthy YouTube videos, mostly instructional-type videos from Google Developer Advocates and the like, explaining how to use APIs, tools, etc. They're good, but every time I look at one and see that it's 45 minutes, or 70 minutes, or whatever, I kind of cringe and sigh. Sometimes I just put it on a "to watch later" list, and maybe I don't get around to it for a long time, if ever. Recently I discovered a useful way to shave a good chunk of time off that watching experience. It's been around for a while, but I wasn't aware of it. YouTube has a trial version of an HTML5 video player that allows you to set the playback speed to 1.5x or 2x normal speed. I find 1.5x to be useful; 2x seems to be too fast if you want to understand the audio, but it could be useful for fast-forwarding to the next interesting part.

For details on enabling this feature, checkout the write-up here.

excluding src\main\resources from source folders in IntelliJ build

Real quick... I recently switched from Eclipse to IntelliJ, and one thing that's been annoying me is that IntelliJ keeps putting the src\main\resources folder of my Android project into its list of source folders.  Removing it only helps temporarily; it gets restored again later (I think when I build from the "maven projects" window). Solution: exclude this folder at the compiler level, in the project settings.  File->Settings->Compiler->Excludes.

Credit for this solution goes to Sergey Evdokimov, who posted it here.

Maven enforcer plugin vs. dependencyManagement

I recently found myself in a situation where I needed to detect whether my maven dependencies, both direct and indirect (transitive), were resolving to inconsistent versions. For example, let's say that artifact A depends on B and C, and B also depends on C.  When building A, I want to know if it is picking up two different versions of C, one directly, and one transitively through B.

As with all Maven problems, "there's a plugin for that" -- in this case, the maven-enforcer-plugin.  It has a variety of interesting rules, but the one that addresses the need I was having is called "dependencyConvergence".

So, I plugged it in to a top-level parent POM, so I could use it in all my projects:

<project>
  ...
  <build>
    ...
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-enforcer-plugin</artifactId>
        <version>1.1.1</version>
        <executions>
          <execution>
            <id>enforce</id>
            <configuration>
              <rules>
                <DependencyConvergence />
              </rules>
            </configuration>
            <goals>
              <goal>enforce</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
    ...
  </build>
  ...
</project>

I use Eclipse with m2e, and I wanted this enforcement to happen in my Eclipse builds, too, so I also added:

<project>
  ...
  <build>
    ...
    <pluginManagement>
      <plugins>
        <pluginExecution>
          <pluginExecutionFilter>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-enforcer-plugin</artifactId>
            <versionRange>[1.0,)</versionRange>
            <goals>
              <goal>enforce</goal>
            </goals>
          </pluginExecutionFilter>
          <action>
            <execute />
          </action>
        </pluginExecution>
      </plugins>
    </pluginManagement>
    ...
  </build>
...
</project>

I ran a build, and sure enough, I did have some mismatches.  This is a really handy plugin -- I have a decent number of my own artifacts involved, plus a variety of 3rd party ones that    show up frequently in my projects, and with all of them getting updated pretty regularly, it's pretty tough to keep track of everything.

In one case where I had a mismatch, I decided to resolve the problem by moving the specification of C's version up to a parent POM shared by A and B.  Two options occurred to me:

1) I could specify a property like

<c.version>1.2.3</c.version>

and have A's and B's POMs use that inherited property in their definitions of the C dependency.  Or,

2) I could put an entry for C into the parent POM's dependencyManagement section:

<dependencyManagement>
  <dependencies>
    <dependency>
     <groupId>org.foo</groupId>
     <artifactId>c</artifactId>
     <version>1.2.3</version>
    </dependency>
  </dependencies>
</dependencyManagement>

and omit C's version from A's and B's POM.

I tried #2 first, since it seemed a little simpler.  As a first step, I added the dependencyManagement entry to the parent POM and removed the version number for C from A's POM, then ran a build.  Guess what:  maven-enforcer-plugin stopped complaining!  But wait, I didn't change B's POM yet; I should still have a discrepancy, shouldn't I?  I thought that all dependencyManagement did was specify default versions for descendant POMs that omitted the version for that dependency.  I checked my Maven: The Definitive Guide book to see if there was more to it.  Nope, no mention of any other purpose or side effects.  I checked the Sonatype web site's description, in case it was more detailed.  Nope.  Hmm.  Then I went to the horse's mouth, the Apache docs, which say:

Dependency management - this allows project authors to directly specify the versions of artifacts to be used when they are encountered in transitive dependencies or in dependencies where no version has been specified. In the example in the preceding section a dependency was directly added to A even though it is not directly used by A. Instead, A can include D as a dependency in its dependencyManagement section and directly control which version of D is used when, or if, it is ever referenced.

[Note: that page is worth a detailed read; it has some good examples which helped firm up my understanding.]

Interesting.  So the version specified in dependencyManagement serves as a default value if none is specified in a descendant POM (but doesn't override the value in a descendant POM if one is specified).  However, it does override a specified value in a transitive dependency.  Because of this behavior, the version of C in B's POM was being overridden, and therefore maven-enforcer-plugin didn't detect the discrepancy.

This dependencyManagement behavior has pros and cons.  On one hand, you can use it to silence the maven-enforcer-plugin in situations where you can't get all the artifacts involved to use the same version (as might be the case if there are 3rd party artifacts involved).  Of course, if you do that, you're taking a risk that the things could go awry at runtime, if the version you specify in dependencyManagement is incompatible in some way with an artifact that had wanted to use a different version.  But sometimes you don't have a choice, and in this situation you should most likely choose the highest of the requested versions, since it's possible that it contains bug fixes or features needed by the artifact that requested it.

The downside of using dependencyManagement willy-nilly as a DRY technique is precisely that maven-enforcer-plugin will no longer give you a heads up about those discrepancies.

So what I'm doing now is this:

  • I don't put dependencies in the dependencyManagement section of my top-level POM.  I want to be alerted by maven-enforcer-plugin when I've got mismatches.  Instead, I use version properties, as mentioned in my approach #1 above.
  • When maven-enforcer-plugin notifies me of discrepancies, I try to see if I can get the artifacts involved to use the same version of the divergent dependency.  If all the dependencies involved are in my own artifacts, I try to get them aligned on the same version of the dependency.  If some artifacts are mine and some are from 3rd parties, I try to align my dependences with the 3rd parties, and/or look for other versions of the 3rd party artifacts that have dependency versions that align with each other, and my code.
  • If after doing the above, I still have unresolvable discrepancies, I choose what I think is the "best fit" version of the problematic artifact and specify that in the dependencyManagement section of the project POM where maven-enforcer-plugin reported the problem (not in my top-level POM).  I add a comment to the dependency declaration in that POM noting the issue and the workaround, so that in the future, should I upgrade to a newer version of the dependency, I'll see the note and can revisit whether the discrepancy can possibly then be resolved.