RSS
 

Archive for the ‘Maven’ Category

Maven Plugins v0.2.1 – re-written and open-sourced!

05 Mar

A "0.1" release of these Maven plugins back in November brought a lot of attention to the project, which showed me that other Maven developers find them as useful as I do. Later, people started to send me new suggestions and open YouTrack issues which I had an extreme pleasure to work on.

Version "0.2.1" was recently released and I believe this version is of paramount importance and it is much more than just an upgrade. Lots of things have changed for the project in addition to features added and bugs fixed:

  • Lots of people have helped me to work on this version by talking to me personally, over e-mail or by opening issues. A big thank you to all of you! Without your impact, ideas and bug reports this release would contain much less.
  • The code was re-written in Groovy and open-sourced. Writing Maven plugins in Groovy is such a big fun, I’ll be talking about it in “Groovy Builds” session at Gr8Conf this year. Come to see how Maven can be better!
  • A separate testing project was created with hundreds of thorough tests and examples. A GCommons library was extracted from the code into a standalone project.
  • Documentation was updated and GroovyDoc is now available as well. But if you’re short of time here’s a quick presentation. The project now has its own mailing list and you’re welcome to join in order to stay informed and take part in features discussions and prioritizing future progress.
  • The project gets more exposure: the Spring issue of Methods & Tools will come out with my article describing the plugins’ purpose and advantages for less technical people, and GroovyMag March 2011 just came out with an article about GCommons. And if all goes well, the hudson/jenkins plugin will be covered by “Jenkins: The Definitive Guide” as John Ferguson Smart kindly accepted my proposal to contribute to the book. This sounds really nice and I hope this is just the beginning.
  • JFrog and JetBrains tools keep working so well that I’m now convinced that a combination of Artifactory, TeamCity and YouTrack is an excellent option these days.


Now, what actually changed in this release? Versions "0.2" and "0.2.1" release notes are available in YouTrack and on the Wiki but here are some highlights:

  • All plugins now support a <runIf> conditional execution. It allows to invoke them conditionally, something that is otherwise impossible with Maven.
  • "maven-copy-plugin" – bullet-proof FTP download, Zip entries unpack, archives update, <runIf> per <resource>, FTP/SCP uploads.
  • "maven-hudson-plugin" – free-style jobs, CVS support, <properties>, <authToken>.
  • "maven-assert-plugin"<assertGroovy> with File.directorySize(), very handy in tests!
  • "maven-sshexec-plugin" – multiple commands support, key-based authentication, echo of the current directory and commands executed.


Now, what’s next? A lot. I also plan to polish GroovyDocs as much as possible.

 

Jenkins/Hudson Maven Repositories

17 Jan



Some locations to keep in mind when you work with Hudson:


Update

After recent Jenkins fork the situation has now changed (many thanks to @abayer and @hudsonci for the info!)

 
 

New Maven plugins released!

14 Nov



Note, an update is available.

After a lot of work I released version "0.1" of the following Maven plugins:

  • "maven-copy-plugin" is an alternative to Maven plugins like assembly, resources, dependency, and truezip. Its purpose is to make working with archives and dependencies very easy.



    It is a Swiss Army knife if you need to copy, pack and unpack files, archives and Maven dependencies. Content replacement, network support, Groovy extension points, attaching archives created as Maven artifacts – it is possible to perform all operations in a single Maven plugin! Oh boy, just give it a try.

  • "maven-hudson-plugin" allows to generate Hudson jobs, keeping any amount of them in a single POM. Jobs can be organized hierarchically with inheritance and can invoke each other, Artifactory deployment is supported as well. Managing tens or hundreds of Hudson jobs becomes possible when they are kept in one place and inherit each other with a sensible defaults.
  • "maven-spring-batch-plugin" allows to invoke Spring Batch jobs as part of Maven build.
  • "maven-mail-plugin" allows to send mails with attachment from Maven.
  • "maven-sshexec-plugin" allows to execute commands on a remote server over ssh.
  • "maven-properties-plugin" allows to create Maven properties dynamically with Groovy snippets.
  • "maven-timestamp-plugin" allows to create a timestamp Maven property.
  • "maven-assert-plugin" allows to verify various build assertions: properties are defined, files exist and files/directories content is identical.
  • "maven-find-plugin" allows to set a Maven property to location of folder dynamically found for each module built. It helps in situations where build needs to access files in other locations than the current module.
 

Neat Delicious trick – keywords combination

26 Aug

The real beauty of Delicious lies in keywords combinations.

I mentioned already that Delicious is my #2 most favorite productivity tool. Within time I developed a set of the most frequently-used keywords in the right column that can be combined with tags in the left column:

"hudson" - Mailing list - "ml"
"spring" - Issue tracker - "jira"
"ant" - API documentation - "api"
"jfrog" - Documentation - "doc"
"groovy" - Maven repository - "repo"
"maven" - Source code browsing - "code"


Now with a "d"-keyworded Delicious search I only need to type "d spring api" to get to

Lots of other useful combinations are also available:

"groovy ml" "hudson ml" "spring ml" "maven ml" "jfrog ml"
"groovy jira" "hudson jira" "spring jira" "gmaven jira" "jfrog jira"
"groovy api" "java api" "spring api" "maven api" "apache api"
"java7 doc" "java doc" "spring doc" "css doc" "html doc"
"groovy repo" "hudson repo" "apache repo" "plugins repo" "jfrog repo"
"groovy code" "hudson code" "spring code" "gmaven code" "groovypp code"


So jumping to a mailing list or API documentation for X is just a matter of "d X ml" or "d X api". Fast!

 

Configuration Management position – can be done by anyone. Or can it?

21 Aug

Configuration Management was always my passion.

Somehow, I have always had this thing for builds. I don’t know why, it just happens to be that way. Over the last 10 years I have accepted various development positions, but very few were actually related to CM. Occasionally, I accepted CM tasks for the joy of it. But there were other reasons: most of the time any given software project is a mess at the CM level. Secondly, most projects on which I was working had no one assigned to this job.

Somehow, builds were supposed to take care of themselves. However in practice this does not happen magically by itself: builds are usually written by some poor guy, temporarily assigned to this task with one goal in mind; to get it over with as soon as possible. And I don’t blame him.

It made me think. What’s wrong here? Why does it happen this way, that very few projects can demonstrate well written build logic, where code is reused and there’s no place to copy-paste? Why do some managers believe there’s absolutely no need to assign a dedicated resource to deal with CM issues and it can be easily taken care of by any developer? And why when these managers experience a messy environment they are still not convinced otherwise?

Lots of questions. I’m going to try and answer some of them.

Why does it happen this way that very few projects can demonstrate well written build logic, where code is reused and there’s no place to copy-paste?

  • Most developers don’t like dealing with builds.

    This is the root of the problem. From what I have seen throughout my career, developers really don’t like dealing with builds. My guess is that it’s just plain boring and unexciting for most “normal” developers and you need to be somewhat abnormal to even remotely like it. What’s exciting about reorganizing files and watching closely how archives are actually created? Not much I suppose.

  • Build code is not shipped and you get no credit for improving it.

    Build logic is usually hidden from people’s eyes: “We just run this batch, we don’t really know how it works”. Since in most cases it is not the company’s business to sell their builds, the incentive to understand and improve them is very low. No customer gets to see the build in any event.

  • Excellent build tools have not existed for years.

    First there was Ant and there is Maven. Why were they not-so-good? They made two important things hard: custom or conditional build logic and reuse. Lack of built-in conditions made builds full of variables, flags and other awkward ways to simulate a simple "if". Lack of built-in reuse functionality made people copy-paste tons of code without ever trying to organize it.

    It was Ant which made an awfully wrong assumption: “There’s no place for "if"s and loops in your builds. Builds should be straightforward and go from A to B to generate a C, no questions asked.” Ant-Contrib was a savior here but reusing someone else’s code was still not an option; <macrodef>s only brought their own issues. Eventually, people turned to “copy-paste”, the best re-usability solution around.

    In Maven, conditional logic and reuse are also far from perfect. To a very limited extent conditional logic can be done with profiles and Ant/Groovy snippets while reuse is provided by <parent>-ing other POMs. I believe this is not flexible and elegant enough. In addition, Maven declarative nature makes any custom build tweaks extremely hard to implement: if there’s no attribute for what you want – you’re out of luck. The only sensible way to deal with all those limitations is to develop Maven plugins for every customized need you might have. Only then one can keep his POMs sane, not blowing to zillions of Ant tasks. But plugin development is not accepted readily by most developers so they usually turn to "maven-antrun-plugin" and .. here we have all Ant issues again.

    The problem with major build tools we have had for years is that they are mostly about straightforward build steps rather than about intelligent build logic. They lack basic build language which is nicely taken care of today by Gradle which has realized that builds are programs and deserve their own build language and build model. When Hans Dockter, the creator of Gradle explained that builds always have their own logic and should be taken as seriously as a production code, I was extremely happy to hear that. Finally, there’s a tool creator who gets it.

Why do some managers believe there’s absolutely no need to assign a dedicated person to deal with CM issues?

  • A dedicated CM resource is a wasted salary that contributes little to the company’s mission and profitability.

    This is so untrue but, unfortunately, that’s exactly how a CM position appears to some managers: a waste. Managers are unable to get answers to corporate questions such as “Can you demo what you do? Can you sell it?” In the absence of any commercially viable answers they wonder why a CM is required at all. Ironically, the most important aspect of any project gets the least attention. Projects with poor build logic are extremely hard to develop, maintain, test and release. It surely comes back to money and lack of understanding but some people fail to see it this way.

    If management believes that dedicated CM positions are not required then why do they keep an IT team? They can’t demo their work either. CM is required to keep things in order and to keep projects from falling apart.

    One possible way to provide a good explanation for the real value of a CM position is to show the cost of not having one. Usually it shows itself as delayed releases, people spending valuable time on activities that are not part of their jobs, notable time it takes to upgrade or change large portions of code, lack of a clear internal and external release processes and, as a result, a great deal of resources, energy and time wasted. And time is money.

    I have no doubt if I had to measure benefits of having a good CM it will always outweigh the mere salary.

Why can’t you split CM tasks evenly between all developers? It can be done by anybody, right?

This is a bad myth.

  • If you split responsibility nobody owns the problem and no one does anything about it.

    Software developers are far too busy to think of ways to improve builds. They can patch it somehow to remove the blocker out of the way but don’t expect them to give serious thought or make an effort regarding any build issue. Multiplied by developers’ aversion to builds in general, no wonder this approach produces little if any results.

  • CM position requires a very specific set of skills.

    As any other position, this one requires a person with a set of skills matching the job requirements. Why wouldn’t you split graphic design, backend logic or DBA tasks evenly between all developers? How would your application look if everybody was responsible for drawing icons, crafting RDBMS schema, and defining product scope? We surely know those tasks should be performed by specifically skilled people in an organization but, somehow, when it comes to CM “anybody can do it”. Why, oh why?

What are CM responsibilities?

It depends on your definition of CM. In some companies CM personnel are busy with baby-sitting ClearCase; they don’t get to write or think about actual builds. My definition of a CM’s responsibilities is as follows:

  • Choose, install and maintain build servers and tools.
    Consider upgrade or migration when a better build tool is being provided by the market.
  • Be deeply involved in and throughout the development process.
    “Outsider” view works much worse as it lacks knowledge required for making critical decisions, improvements and optimizations.
  • Monitor and “align” third-party library versions.
  • Implement build logic, educate developers and provide support where needed.
  • Constantly review company’s builds and search for overlaps, contradictions and unnecessary complexities.
    Develop solutions to prevent these.
  • Define and enforce version control system branching policies and guidance.
  • Define and enforce general build practices, product versioning, and release processes.

As one can see, the list is not short and it is far from being a naive one-liner like “Write Ant scripts” as some managers may conceive CM duties.

What are the skills required to perform the above duties well?

  • Genuine and natural ability to get things in order, always do the right thing and keep it that way!

    From my experience, a good CM person is a gatekeeper to prevent disorganization, lack of knowledge, interest and whatever it is that is preventing companies from keeping their projects organized, timely built and tested. The reality can be sad at times but a good CM professional fights it and doesn’t allow himself to give up and become careless. Left to their own devises projects may eventually derail into a clutter and a good CM is supposed to alert and block any such attempts.

  • Good development skills.

    I think it is crucial for CMs to be good developers because sometimes existing tools are inadequate and it requires a CM to develop new more appropriate tools. These tools can be Maven plugins, custom Ant tasks, Hudson plugins or some internal Web applications; whatever makes things tick. So good knowledge of Ant, Maven, Java and Groovy is very advantageous. Armed with good Java knowledge, CMs are able to understand and probably fix a lot of build failures, without resorting to external help. It’s about saving time and developing new solutions, whenever required.

  • Balls, curiosity, and good appetite for upgrades.

    Historically, companies are very reluctant to upgrade their build infrastructures, libraries and surrounding tools, like JDK. It can bring instability, failures and nobody really wants to deal with these. Indeed, it takes some will-power to undertake an upgrade in an organization. The upgrader is invariably responsible if anything fails and he is the one who needs to fix it. Consequently, one gets to witness organizations running with outdated versions of Ant, Tomcat, Spring and JDK for no other reason than the fear of upgrades. Good CMs should always be curious about new versions and insist on upgrades as part of their job irrespective of the resistance.

  • Good troubleshooting skills.

    One of the least exciting aspects of CM’s job is the obligation to deal with build failures. Sometimes it’s all too overwhelming – non-stop failures for various reasons: bad commits, lack of disk space, wrong OS, missing setups, and non-reproducible Hudson errors. Occasionally, it requires some emotional stability not to fall apart under the onslaught of problems but what it always requires is good troubleshooting skills: an ability to quickly understand what went wrong from looking at log files and analyzing all changes that were brought in recently. There are ways to deal with all of these, like bringing a system back into a working state and thereafter reverse engineering it to the point of failure, step by step.

  • Good communication skills.

    For any CM to successfully manage this otherwise challenging and sometimes thankless job requires excellent communications and interpersonal skills. It requires CM to convince some employees to change inadequate old habits and educating developers and users about the importance of good CM practices.

In conclusion, I would say that there is no substitute for a good CM in any serious organization that prides itself and has an above average development environment. I tend to compare the CM’s position to that of a building architect who is in charge of the overall construction design, its services, function, maintenance, security, and infrastructures. Someone needs to have a bird’s-eye view of all development activities. In theory Software Architects should be fulfilling this job but in practice it is CM role.




 
10 Comments

Posted in Ant, Maven, People

 

JFrog: To Build or Not to Be

05 Aug

JFrog’s “To Build or Not to Be” seminar was an exceptional one. Usually, there are very few events fully devoted to the subject of builds and build tools. Lucky us we had this one with so many key people of today’s build arena:

Two of the sessions are now available online in JFrog blog, a big number of photos are available in Picasa album of Guy Nir.

I allowed myself to ask participants some questions.

Sergey Anchipolevsky, Max Feldman – TeamCity:

“What does "Git (JetBrains)" Git integration of TeamCity mean?”

It’s just a version of Git plugin developed by JetBrains, to differentiate it from previous Git plugins.

“Is it possible to "tag" a YouTrack issue?”

That’s a YouTrack question but yes, you can tag an issue.

“Is it possible to backup YouTrack issues?”

Sure, you can schedule YouTrack database backups with a cron expression or run it manually.

“Is it possible to re-order YouTrack issues by drag-n-dropping them, similarly to how it is done in Nozbe?”

No, it can’t be done. YouTrack isn’t really a task management tool, like Nozbe. It is an issue tracker which is something different. The order between issues is specified by a "sort by" criteria so they can’t be arbitrarily re-ordered with drag-n-drop. But you should probably take a look at checkvist.com, a simpler task management tool developed by JetBrains developers.

“Ok, TeamCity question. What do you think of cloud-based TeamCity version, similar to Artifactory Online. Can it be done?”

Oh, that’s a good one. First of all, let’s get something clear. You can’t provide a SaaS solution for a build server. Normally, SaaS solutions, like Artifactory Online that you have mentioned, are based on a shared resources, hosted by provider. But something like a build server is too resource-hungry and can’t be shared with other users.

My comment: I agree. Experience shows how unshareable build servers are. You really want a dedicated machine for each one of them, trying to run too many builds on the same machine may quickly bring the server to its knees and overall response time drops dramatically.

But something else can be done. First of all, you can run build agents on EC2 today. Second, we can provide TeamCity images ready to be run on EC2 as well. But it’s always better if you run main TeamCity server inside your organization, on your own IT infrastructures. We haven’s seen too many customers willing to out-source the build server completely: networking issues, server configurations, additional setups, security .. it’s too much of a pain and, again, can hardly be shared between different users.

“I see, thank you. Is it possible to develop plugins for TeamCity?”

Sure!

Yoav Landman – Artifactory:

“After hearing your session about module development options in Java – what do you think of JPF? Is it somehow a player in today’s Java module-space?”

I looked at JPF several times before as an application level module system, but I don’t think it amounts to a Java language module system. You can incorporate it into an application but you can’t build or run a full application based strictly on JPF modules (last time I checked).

“You mentioned Java moduling system is not united and fragmented, we have lot’s of approaches and various repos available. Can “repo1″ be *the one*?”

It kind of is at the moment and there are no much alternatives available. I wish it would be more developer friendly, though.

“As people are running more and more Artifactory Online instances, does it contribute to overall module-space fragmentation? Don’t get me wrong, I love it and had a great success in providing a Maven support for the Groovy++ project with a help of groovypp.artifactoryonline.com. I have my own repo set up at evgeny-goldin.org/artifactory that I’m about to use for my personal projects. So it’s cool, by all means. Still, the fragmentation issue you have just mentioned during the session just made me wonder .. “

Having a central repository and a central URL to get things from is a great thing. However, Maven central brings some long-lasting issues with it: the existence of module developers is not obvious and artifacts cannot be linked back to them; publishing is not straightforward – rather than getting an account and a simple Web UI/REST deploy, you need to set up rsync or learn a commercial tool to do that – in both cases the final published artifact looses relation to its creator account; repositories provide no REST API, there’s no access to statistics, and mostly – no searches: rather than sending a query to Central you have to download index file and search on the client side. I think these are the main concerns that keep people managing their public repositories on apache/sf/google-code/svn/artifactory/nexus etc.

Hans Dockter – Gradle:

“Gradle is a truly awesome build tool. Are you planning to provide a way to invoke Maven plugins from Gradle?”

Yes, it is of very high priority, we will provide a way to “import” and run an existing "pom.xml"

“In fact, I was thinking more of invoking a plugin directly, given its <groupid>, <artifactid>, and <version>. Similarly to how it is done by Mojo Executor .. “

Ah, right, right, this one. Sure, it should be done as well, although it is not simple, you know. To invoke a Maven plugin you need to “bind” it with a Maven container but we may probably trick into thinking there’s a Maven container while it will be talking to a Gradle run-time environment. Anyway, it’s definitely on our TODO list.

“The reason I ask is to ease Maven to Gradle migration or simply re-use an existing Maven plugins, some of which are really good! Now, I believe Gradle is a great tool but it requires a serious understanding of what you’re doing. In some aspects, it reminds me of Git where some people consider it to be too complex sometimes”

Yes, there’s a need to provide a really simple guidance for a people to switch between the tools or adopt a new one, like Gradle. But you need to understand your tool, there’s no doubt about it.

It was time to say good bye. But I hope to see you all again!
A big thanks to Guy Nir and Shlomi Ben Haim for generously allowing me to use some of the photos they have made.

 

Spring: Ant-like files pattern matching

27 Jul



Spring Batch job definition:

<bean>
    <property name="resources" value="file:/${path}/some.*.pattern.zip"/>
    ...
</bean>

"${path}/some.*.pattern.zip" is right, I can guarantee that. Double-checked!
So why Spring Batch complaints "No resources to read" and does nothing?

Argh .. probably, has something to do with files pattern matching.

All right, I was curious about Ant-like files pattern matching in non-Ant environments for a long time already.
How one does that?

For "maven-copy-plugin" I’ve managed with "file-management" module:

<dependency>
    <groupid>org.apache.maven.shared</groupid>
    <artifactid>file-management</artifactid>
    <version>1.2.1</version>
    <scope>compile</scope>
</dependency>
import org.apache.maven.shared.model.fileset.FileSet;
import org.apache.maven.shared.model.fileset.util.FileSetManager;

FileSet fs = new FileSet();

fs.setDirectory( .. );
fs.setIncludes( .. );
fs.setExcludes( .. );

String[] files = new FileSetManager().getIncludedFiles( fs )

but that’s Maven. How is it done in Spring?
Well, debugging is always fun!

What a journey. But we have the answer, it’s "org.springframework.util.AntPathMatcher". Doesn’t surprise me, "org.springframework.util" package was always full of nice utilities. One more to a toolbox!

P.S.
"No resources to read" ?
"file:/" was not required:

<bean>
    <property name="resources" value="${path}/some.*.pattern.zip"/>
    ...
</bean>

Previous version was converted to something like "file:c:\file:/", but this one worked just fine.
I guess this version would also work, according to PathMatchingResourcePatternResolver Javadoc:

<bean>
    <property name="resources" value="file:${path}/some.*.pattern.zip"/>
    ...
</bean>

One more example where a single "/" is of crucial importance. I love this job!

 
No Comments

Posted in Ant, Maven, Spring

 

Hudson and Artifactory Maven repository

17 Jul

For a long time I was sure there’s no Hudson Maven repository.

I was wrong:

<dependency>
    <groupid>org.jvnet.hudson.main</groupid>
    <artifactid>hudson-war</artifactid>
    <version>1.373</version>
    <type>war</type>
</dependency>
<dependency>
    <groupid>org.jvnet.hudson.plugins</groupid>
    <artifactid>greenballs</artifactid>
    <version>1.6</version>
    <type>hpi</type>
</dependency>
<dependency>
    <groupid>org.jvnet.hudson.plugins</groupid>
    <artifactid>artifactory</artifactid>
    <version>1.2.0</version>
    <type>hpi</type>
</dependency>

Similarly, Artifactory:

<dependency>
    <groupid>org.artifactory</groupid>
    <artifactid>artifactory-web-war</artifactid>
    <version>2.2.5</version>
    <type>war</type>
</dependency>

And Maven itself:

<dependency>
    <groupId>org.apache.maven</groupId>
    <artifactId>apache-maven</artifactId>
    <version>2.2.1</version>
    <classifier>bin</classifier>
    <type>zip</type>
</dependency>

Why would one want to get Hudson, Artifactory and Maven distribution through Maven?
In our case, we create a Tomcat setup with Hudson, Artifactory and Maven already installed and configured, I’ll write about this project later.

 

Groovy 1.7.3: AnnoMojo + GroovyMojo!

27 Jun



I waited a lot. Oh boy, I did.

 

.. Rewind back half a year ..

 

Writing Maven plugins, or MOJOs, is a real need when you work with Maven. It just feels unnatural not to.

Default Maven behavior and set of plugins is only good for common situations and the moment you’re doing something unusual, like running Spring Batch jobs or generating Hudson jobs in your POM, Maven doesn’t really deliver. In the last year, I had to develop about 10 Maven plugins, now waiting for a final Thomson Reuters approval to be open-sourced (stay tuned!)

Initially, I used Java but later switched to Groovy, for an obvious reasons. With Gmaven plugin it is very easy to develop Groovy Mojos. Good!

The only problem I had after switching to Groovy is lack of Anno Mojo support providing Java 5 annotations to MOJO developer.

Java:

@MojoGoal("doIt")
@MojoPhase("package")
public class MyMojo extends AbstractMojo
{
    @MojoComponent
    private ArtifactFactory artifactFactory;

    @MojoParameter(expression = "${project}", required = true)
    private MavenProject project;

    @MojoParameter (required = false)
    private String runIf;
    ...
}

Groovy:

@MojoGoal("doIt")
@MojoPhase("package")
class MyMojo extends GroovyMojo
{
    @MojoComponent
    def ArtifactFactory artifactFactory;

    @MojoParameter(expression = "${project}", required = true)
    def MavenProject project;

    @MojoParameter (required = false)
    def String runIf;
    ...
}

Groovy version didn’t work :(
Meet “GROOVY-4118″ – “JavaStubGenerator doesn’t generate annotations available in Groovy code”

 

.. Fast forward to Groovy 1.7.3 release ..

 

Shortly before Groovy 1.7.3 release the issue above was addressed and fixed by Paul King and Jochen Theodorou. After some more attempts I made it work and it felt really-really good to get back annotations in Groovy Mojos!

@MojoGoal("doIt")
@MojoPhase("package")
class MyMojo extends GroovyMojo
{
    @MojoComponent
    public ArtifactFactory artifactFactory;

    @MojoParameter(expression = "${project}", required = true)
    public MavenProject project;

    @MojoParameter (required = false)
    public String runIf;
    ...
}

It is required to use:

  • public modifiers
  • Groovy fields

This will not work:

class MyMojo extends GroovyMojo
{
    @MojoParameter (required = false)
    def String runIf;

    @MojoParameter (required = false)
    String something;
}

 

"pom.xml":

<dependencies>
    <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
    <!-- To use Anno Mojo annotations in Groovy code -->
    <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
    <dependency>
        <!-- http://www.jfrog.org/artifactory/plugins-releases/org/jfrog/maven/annomojo/maven-plugin-anno/ -->
        <groupid>org.jfrog.maven.annomojo</groupid>
        <artifactid>maven-plugin-anno</artifactid>
        <version>1.3.3</version>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupid>org.codehaus.groovy</groupid>
        <artifactid>groovy-all</artifactid>
        <version>1.7.3</version>
        <scope>compile</scope>
    </dependency>
</dependencies>

<build>
    <plugins>
        <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
        <!-- To generate Java stubs and compile Groovy classes -->
        <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
        <plugin>
            <groupid>org.codehaus.gmaven</groupid>
            <artifactid>gmaven-plugin</artifactid>
            <version>1.2</version>
            <executions>
                <execution>
                    <id>generate-stubs</id>
                    <phase>generate-sources</phase>
                    <goals>
                        <goal>generateStubs</goal>
                    </goals>
                </execution>
                <execution>
                    <id>compile-groovy</id>
                    <phase>process-sources</phase>
                    <goals>
                        <goal>compile</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <providerselection>1.7</providerselection>
                <verbose>true</verbose>
                <sources>
                    <fileset>
                        <directory>${projects.basedir}/src/main/scripts</directory>
                        <includes>
                            <include>**/*.groovy</include>
                        </includes>
                    </fileset>
                </sources>
            </configuration>
            <dependencies>
                <dependency>
                    <groupid>org.codehaus.gmaven.runtime</groupid>
                    <artifactid>gmaven-runtime-1.7</artifactid>
                    <version>1.2</version>
                    <exclusions>
                        <exclusion>
                            <groupid>org.codehaus.groovy</groupid>
                            <artifactid>groovy-all</artifactid>
                        </exclusion>
                    </exclusions>
                </dependency>
                <dependency>
                    <groupid>org.codehaus.groovy</groupid>
                    <artifactid>groovy-all</artifactid>
                    <version>1.7.3</version>
                </dependency>
            </dependencies>
        </plugin>

        <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
        <!-- To "activate" Anno Mojo during plugin metadata generation -->
        <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
        <plugin>
            <groupid>org.apache.maven.plugins</groupid>
            <artifactid>maven-plugin-plugin</artifactid>
            <version>2.5.1</version>
            <dependencies>
                <dependency>
                  <groupid>org.apache.maven.plugin-tools</groupid>
                  <artifactid>maven-plugin-tools-api</artifactid>
                  <version>2.5.1</version>
                </dependency>
                <dependency>
                    <!-- http://www.jfrog.org/artifactory/plugins-releases/org/jfrog/maven/annomojo/maven-plugin-tools-anno/ -->
                    <groupid>org.jfrog.maven.annomojo</groupid>
                    <artifactid>maven-plugin-tools-anno</artifactid>
                    <version>1.3.3</version>
                    <scope>runtime</scope>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>
</build>

Also, I use the following base class for all Groovy Mojos with commonly-used @MojoParameters:

/**
 * Base GroovyMojo class
 */
abstract class ClfGroovyMojo extends GroovyMojo
{
    private static final Log LOG = new SystemStreamLog()
    public  static       Log getLog () { LOG }

    @MojoParameter ( expression = '${project}' )
    public MavenProject mavenProject
    public MavenProject mavenProject() { this.@mavenProject }

    @MojoParameter ( expression = '${session}' )
    public MavenSession mavenSession
    public MavenSession mavenSession() { this.@mavenSession }

    @MojoParameter ( expression = '${project.build.directory}' )
    public File buildDirectory
    public File buildDirectory() { this.@buildDirectory }

    @MojoParameter ( expression = '${project.build.outputDirectory}' )
    public File outputDirectory
    public File outputDirectory() { this.@outputDirectory }

    @MojoParameter ( expression = '${project.basedir}' )
    public File basedir
    public File basedir() { this.@basedir }

    @MojoParameter ( defaultValue = '${localRepository}' )
    public ArtifactRepository localRepository
    public ArtifactRepository localRepository() { this.@localRepository }

    @MojoComponent
    public PluginManager pluginManager
    public PluginManager pluginManager() { this.@pluginManager }
}

Let me know if something doesn’t work for you. I may provide a complete example of Groovy Mojo.

 
 

Artifactory Online – the case of distributing Groovy++

05 May

After working with open source Artifactory version and thoroughly exploring it’s add-ons I knew it would come a moment to put my hands on its cloud solution – Artifactory Online. It just made sense to “close the loop” this way .. Тhe moment I’ve heard about online instance, running 24×7 without having to take care of anything – it sounded really, really nice.

I can’t say we spend a lot of time administering our open source version in Thomson Reuters. Quite the opposite – I only need to take it down for upgrades from time to time. But it still takes us a machine. A virtual one, of course but still – that’s CPU and memory that could be well spent somewhere else. So having online instance not only gives a peace of mind freeing everybody from taking care of one more server and one more database – it frees some hardware resources as well.

Well, a beauty of cloud computing, when it works. And Artifactory certainly does!

But my first use of Artifactory Online was for slightly different purpose – Maven support for the Groovy++ project. There was a clear need to host Groovy++ binaries in a public Maven repo.

What options are available today?

  • OSS repository hosting from Sonatype.
    It’s a good free solution but like any other free solution it only provides you so much: if you don’t mind being at mercy of other people with certain demands about how your POMs should look like – then it’s a good way to go. But I’d prefer my personal repository, where I can configure it the way I want without sharing it with other projects and asking favors. Also, bear in mind you get no security whatsoever – all your binaries would be open to everybody, anytime. And it only works for open-source projects which can be another showstopper.
  •  

  • Another option is to host a public Apache or nginx server and just make the files available following Maven’s naming conventions, like it’s done on "repo1". Not to mention the lack of security (again) – this kind of storage can be fragile to files corruptions: after all it’s just a dumb files storage, not an intelligent repo manager. You can’t use Maven to deploy artifacts and it provides no additional services, like virtual repos, artifacts searching or usage statistics.
  •  

  • Public hosting of open-source Nexus or Artifactory – it’s much better and we can finally protect it the way we want. But we still need to pay for hosting, memory usage, bandwidth usage and we now need to install and administer it on top of everything else. And put some extra protection, may be.
  •  

  • Artifactory Online. The best way to go, if you ask me. Not only it provides a cloud-based 24×7 running Artifactory instance, but it does so with all add-ons installed, so you really get it the ‘Full Monty’! It solves our original problem, to host binaries in a public Maven repo, but it doesn’t stop there, as I’ll show shortly – running a private Artifactory instance brings other advantages to your projects.

We’ve settled with last option, meet http://groovypp.artifactoryonline.com/!
The initial setup went very fast as there were very few things to take care of, actually:

  1. Registration
  2.  

  3. Creating deployment user and "settings.xml". The fact that Artifactory provides a way to generate new “settings.xml” (skip to 00:10:40) and store an encrypted passwords (00:11:55) comes in very handy:

    <servers>
        <server>
            <id>groovypp</id>
            <username>username</username>
            <password>\{ABAeqq\}pIcMooZ8G/2Y2drgC99SDw==</password> <!-- Sample -->
        </server>
    </servers>
    
  4. Instructing Maven about new repositories:

    <properties>
        <repo>http://groovypp.artifactoryonline.com/groovypp</repo>
    </properties>
    
    <distributionmanagement>
        <repository>
            <id>libs-releases-local</id>
            <url>${repo}/libs-releases-local</url>
        </repository>
    </distributionmanagement>
    
    <repositories>
        <repository>
            <id>libs-releases</id>
            <url>${repo}/libs-releases</url>
        </repository>
    </repositories>
    
    <pluginrepositories>
        <pluginrepository>
            <id>plugins-releases</id>
            <url>${repo}/plugins-releases</url>
        </pluginrepository>
    </pluginrepositories>
    

As you see, we’re using new repo not only for <distributionManagement> but as our only Maven repository.
From now on we only talk to groovypp.artifactoryonline.com/groovypp/libs-releases.
This is “virtual repository”, a “gateway” Maven will connect to for retrieving any 3-rd party library. I can now add additional Maven repositories by editing it in Artifactory, there’s no need to update the POM any more when new external repos are added to the project.

After this quick setup I ran it for the first time. I was expecting somewhat slower performance than the one we have in the office where Artifactory is running on the same network. After all, we’re talking here about remote repository running somewhere across the ocean:

But the download was pretty fast. It depends on the bandwidth, of course but I can’t say that significantly more distant repository has slowed me down. UI was very response and Maven’s filling of empty local repo was fast enough as not to notice any significant difference. Good!

Groovy++ project is now happily using Artifactory Online for several months and releases, you’re always welcome to download the latest version manually or give it a try with Maven.

What else can I say about running a private repo like that?

I think the main beauty of it is being able to “go public” in matter of minutes. No setups, no worries – you have your very own binaries storage, intelligent and secured that can be used for any purpose. That’s right, Artifactory can serve any binaries, not necessarily Maven’s artifacts. So one can store there practically anything and then secure or backup it safely.

Makes me think of various App Store services where people publish their Android / iPhone applications and enjoy the ride. That’s good, I believe “going public” should be easy for anyone today – this way creativity meets no entry barriers!

I only have a single request to Artifactory developers – an option to create aliases to existing repo. This would allow to reuse the same repository for different projects or purposes: http://projectA.artifactoryonline.com/ and http://projectB.artifactoryonline.com/ will point to the same Artifactory instance but will be used by different people.

Overall, a very pleasant experience!
Exactly what I was expecting – can’t help it but these guys never disappoint :)