<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>The Cubeia Blog &#187; maven</title>
	<atom:link href="http:///index.php/blog/archives/tag/maven/feed" rel="self" type="application/rss+xml" />
	<link>http://www.cubeia.com/index.php/blog</link>
	<description>Tech Lust and Lust of Words</description>
	<lastBuildDate>Tue, 31 Jan 2012 13:11:30 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>A Google Analytics Plugin for Nexus</title>
		<link>http://www.cubeia.com/index.php/blog/archives/39</link>
		<comments>http://www.cubeia.com/index.php/blog/archives/39#comments</comments>
		<pubDate>Thu, 11 Feb 2010 10:40:12 +0000</pubDate>
		<dc:creator>larsan</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[google analytics]]></category>
		<category><![CDATA[maven]]></category>
		<category><![CDATA[nexus]]></category>
		<category><![CDATA[plugin]]></category>

		<guid isPermaLink="false">http://www.cubeia.com/index.php/blog/archives/39</guid>
		<description><![CDATA[Since Firebase Community Edition uses Maven heavily, I realized I&#8217;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&#8217;s my attempt to write a simple one.
If you&#8217;re an impatient kind, here&#8217;s the source code.
I [...]]]></description>
			<content:encoded><![CDATA[<p>Since <a href="http://www.cubeia.org">Firebase Community Edition</a> uses Maven heavily, I realized I&#8217;d like to track our Nexus repository in Google Analytics. The <a href="http://www.sonatype.com/books/nexus-book/reference/">Nexus Book</a> says that there exists such a plugin already, but apparently now one knows where it is. So here&#8217;s my attempt to write a simple one.</p>
<p>If you&#8217;re an impatient kind, <a href="/docs/misc/tracker-1.0-SNAPSHOT-project.zip">here&#8217;s</a> the source code.</p>
<p>I created the project  in Eclipse, instructions <a href="http://www.sonatype.com/people/2010/01/writing-a-nexus-plugin-using-m2eclipse/">here</a>.</p>
<p>Now, let&#8217;s start off with a &#8220;repository customizer&#8221; which is Nexus extension point we&#8217;ll use to insert a custom request processor into every repository&#8230;</p>
<pre>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;
    }
}</pre>
<p>Not too complicated. We&#8217;re using injection to get hold of the actual tracker components and we&#8217;re inserting it into all repostories.</p>
<p>Wait, <em>all</em> repositories? Yes, and it&#8217;s problem I haven&#8217;t really figured out yet. Ideally I&#8217;d like to track &#8220;hosted&#8221; repositories only. However, we&#8217;ve configured all our builds to use a few common development &#8220;groups&#8221; 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 &#8220;groups&#8221; as equivalent to &#8220;views&#8221; in which case I&#8217;d expect the hosted repository to be called as well, but, no&#8230;</p>
<p>Now, let&#8217;s create a request processor which will react when someone &#8220;reads&#8221; a path in a repository.  We&#8217;ll take it in pieces&#8230;</p>
<pre>@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();
    }

    [...]</pre>
<p>We configure the plugin via system properties (not too beautiful, I know), the &#8220;tracker id&#8221; is the google tracking code id and is mandatory, and the &#8220;refer url&#8221; will be set on the call to GA if available.  We&#8217;re using the <a href="http://code.google.com/p/jgoogleanalytics/">JGoogleAnalytics</a> library to call GA for us. Also, I&#8217;m being naughty and throwing an illegal state exception if the tracker id is missing, since GA updates every 24 hours we&#8217;d like to be notified on errors early.</p>
<p>There&#8217;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:</p>
<pre>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);
    }
}</pre>
<p>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.</p>
<p>Before we go on we&#8217;ll create a small subclass on <em>FocusPoint</em> which we&#8217;ll use for tracking. Since JGoogleAnalitycs is made primarily for applications the focus point will URL encode itself, however, that won&#8217;t work for us, so we need to override it&#8217;s <em>getContentURI</em> method:</p>
<pre>/**
 * 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();
    }
}</pre>
<p>And finally we&#8217;ll tie it all toghether. We&#8217;ll react on &#8220;read&#8221; actions, create a URI (of form &#8216;//path&#8217;) and track asynchronously (which will spawn a new thread for calling GA:</p>
<pre> 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;
}</pre>
<p>And that&#8217;s it. It&#8217;s not perfect though ideally I&#8217;d like to track hosted repositories only, I&#8217;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 &#8220;conf/wrapper.conf&#8221; files), but I&#8217;ll leave those for a rainy day.</p>
<p><a href="/docs/misc/tracker-1.0-SNAPSHOT-project.zip">Here&#8217;s</a> the source code as a Maven project.</p>
<p>Enjoy!</p>
<p><strong>Update:</strong> If you download and try to compile, you will probably be missing the JGoogleAnalytics lib. You&#8217;re welcome to use our, GA-tracked, repository if you like <img src='http://www.cubeia.com/components/com_wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<pre>&lt;repository&gt;
  &lt;id&gt;cubeia-nexus&lt;/id&gt;
  &lt;url&gt;http://m2.cubeia.com/nexus/content/groups/public/&lt;/url&gt;
  &lt;releases&gt;
    &lt;enabled&gt;true&lt;/enabled&gt;
  &lt;/releases&gt;
  &lt;snapshots&gt;
    &lt;enabled&gt;true&lt;/enabled&gt;
  &lt;/snapshots&gt;
&lt;/repository&gt;</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.cubeia.com/index.php/blog/archives/39/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>How to Solve the &#8220;file already exists&#8221; Maven/SVN Problem</title>
		<link>http://www.cubeia.com/index.php/blog/archives/44</link>
		<comments>http://www.cubeia.com/index.php/blog/archives/44#comments</comments>
		<pubDate>Fri, 20 Feb 2009 12:55:14 +0000</pubDate>
		<dc:creator>viktor</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[bug]]></category>
		<category><![CDATA[maven]]></category>
		<category><![CDATA[release]]></category>
		<category><![CDATA[workaround]]></category>

		<guid isPermaLink="false">http://www.cubeia.com/index.php/blog/archives/44</guid>
		<description><![CDATA[If you are using Subversion and Maven, you might have experienced a message that looks something like: svn: File &#8216;/folder/pom.xml&#8217; already exists, when executing the &#8220;mvn release:prepare&#8221; 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 [...]]]></description>
			<content:encoded><![CDATA[<p>If you are using Subversion and Maven, you might have experienced a message that looks something like: <strong>svn: File &#8216;/folder/pom.xml&#8217; already exists</strong>, when executing the &#8220;mvn release:prepare&#8221; goal<strong>.</strong></p>
<p>This has surely caused some frustration for us. After looking around we understood that the underlying <a href="http://subversion.tigris.org/issues/show_bug.cgi?id=3119">bug</a> is in Subversion while the Maven problem is reported <a href="http://jira.codehaus.org/browse/SCM-406">here</a>.</p>
<p>In the latter bug report, there is a <a href="http://jira.codehaus.org/browse/SCM-406?focusedCommentId=146938&amp;page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#action_146938">suggestion</a> for a workaround:</p>
<p>First, execute &#8220;mvn release:prepare&#8221;. When the error message appears, run &#8220;svn update&#8221; and then try again with &#8220;mvn release:prepare -Dresume&#8221;.</p>
<p>This has worked every time for us, but it has not ceased to feel like an ugly workaround.</p>
<p>Good luck!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cubeia.com/index.php/blog/archives/44/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>10 Sure Signs You Are Doing Maven Wrong</title>
		<link>http://www.cubeia.com/index.php/blog/archives/41</link>
		<comments>http://www.cubeia.com/index.php/blog/archives/41#comments</comments>
		<pubDate>Fri, 13 Feb 2009 13:47:58 +0000</pubDate>
		<dc:creator>viktor</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[archiva]]></category>
		<category><![CDATA[artifactory]]></category>
		<category><![CDATA[continuum]]></category>
		<category><![CDATA[firebase]]></category>
		<category><![CDATA[hudson]]></category>
		<category><![CDATA[maven]]></category>
		<category><![CDATA[teamcity]]></category>

		<guid isPermaLink="false">http://www.cubeia.com/index.php/blog/archives/41</guid>
		<description><![CDATA[The &#8220;Maven Frustration Syndrome&#8221; is a severe decease that I don&#8217;t think many developers using Maven have not suffered from. Luckily, there are ways to rub Maven the right way. Here&#8217;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 [...]]]></description>
			<content:encoded><![CDATA[<p align="left">The &#8220;Maven Frustration Syndrome&#8221; is a severe decease that I don&#8217;t think many developers using Maven have not suffered from. Luckily, there are ways to rub Maven the right way. Here&#8217;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.</p>
<p><strong>1. You constantly update and &#8220;mvn install&#8221; everything and the kitchen sink, just to be sure</strong></p>
<p align="left">This is the most common problem I have seen. The fix for this will have benefits for many of the points below. Here&#8217;s a statement that I don&#8217;t think you can find anywhere in the Maven documentation, but that I firmly believe is true:<br />
<em>&#8220;Every Maven artifact HAS to have a home in one Maven repository.&#8221;</em></p>
<p align="left">This means that, in your company, you have to have a repository manager, such as <a href="http://archiva.apache.org/">Archiva</a> or <a href="http://www.jfrog.org/products.php">Artifactory.</a> 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 <a href="https://hudson.dev.java.net/">Hudson</a> for this, but <a href="http://continuum.apache.org/">Continuum</a> or <a href="http://www.jetbrains.com/teamcity/">TeamCity</a> will do the job as well.</p>
<p>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 &#8220;update and install everything&#8221;. If you are working on one module, you should only have to build that module. The other modules will be downloaded to you automatically.</p>
<p><strong>2. You and your colleagues solve the &#8220;dependency not found&#8221; problem by copying someone&#8217;s entire .m2-folder via memory stick</strong><br />
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 &#8220;who has a memory stick?&#8221; dance again. You shouldn&#8217;t even have to fear wiping your local repository entirely, since download speed from the local repository manager should be very fast.</p>
<p><strong>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</strong><br />
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&#8217;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.</p>
<p>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.</p>
<p><strong>4. You have lots of shell scripts / batch files that traverse the target folders of your modules to create a zip file</strong><br />
Maven has a way of doing this, called &#8220;assemblies&#8221;. 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 <a href="/index.php/products/firebase">Firebase</a> to our customers and it works well for us.</p>
<p><strong>5. You have lots of xml in your poms whose only purpose is to copy files into your deploy folders, but it&#8217;s not working properly and it&#8217;s not portable</strong><br />
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&#8217;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.</p>
<p><strong>6. Your build stalls forever on &#8220;checking for updates from xxx-repo&#8221; and you don&#8217;t know why</strong><br />
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.</p>
<p>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&#8217;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.</p>
<p><strong>7. If you work on the release branch, your trunk build might fail (or 1.0-SNAPSHOT should be good enough for everyone)</strong><br />
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.</p>
<p>There is a goal in the release plugin called &#8220;<a href="http://maven.apache.org/plugins/maven-release-plugin/examples/branch.html">branch</a>&#8220;, by running &#8220;mvn release:branch&#8221;, Maven can automatically rename the versions in the poms for you. (Disclaimer, I haven&#8217;t tried this myself, since we usually only branch when we create a release, using &#8220;mvn release:prepare&#8221; followed by &#8220;mvn release:perform&#8221;).</p>
<p><strong>8. All your company internal dependencies end with -SNAPSHOT</strong><br />
The idea of a snapshot seems comforting to developers. It&#8217;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&#8217;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.</p>
<p>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.</p>
<p><strong>9. If you run &#8220;mvn dependency:analyze&#8221; the list of unused and undeclared dependencies is too long to recite before lunch</strong><br />
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&#8217;s way of handling transitive dependencies. Because of this, you can use code in your dependency&#8217;s dependencies and it will compile just fine. The problems come when either you decide to change the scope of that dependency to &#8220;provided&#8221;, 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 <a href="http://uglycoder.blogspot.com/2008/04/flaw-with-mavens-transitive.html">here.</a></p>
<p>Luckily, there is a way to check how many shortcuts you have taken by running &#8220;mvn dependency:analyze&#8221;. 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.</p>
<p><strong>10. When someone releases a new version of a plugin that you use, your builds tend to fail</strong><br />
Maven has for some reason decided that you don&#8217;t need to specify the version of your plugin dependencies. Maven will find the &#8220;latest and greatest&#8221; for you. When a new version of a plugin is released, you will download and use it without knowing it. Sometimes, the &#8220;latest and greatest&#8221; 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&#8217;s internal plugins as well.</p>
<p align="left"><strong>References</strong><a href="http://www.sonatype.com/books/maven-book/index.html"><br />
</a><a href="/maven.apache.org">The Official Maven Site</a><a href="http://www.sonatype.com/books/maven-book/index.html"><br />
</a><a href="http://www.sonatype.com/books/maven-book/index.html">Maven: The Definitive Guide</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.cubeia.com/index.php/blog/archives/41/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

