Friday, March 21, 2014

DevNation 150OFF

A sneak peek into my session about JRebel at DevNation conference in San Francisco :http://blog.arungupta.me/2014/03/anton-arhipov-jrebel-devnation/

Check out the full schedule here: http://www.devnation.org/

Register with promo code 150OFF and get $150 off the registration fee!

Thursday, February 27, 2014

GeekOUT Conference Early Bird Registration is Live!

Registration to GeekOUT conference in Tallinn is now open! Geekout in numbers:
  • 15 amazing invited talks
  • 14 great speakers
  • Hand-picked vendors @ Demogrounds
  • GitHub workshop by Tim Berglund
  • Kickass party
And a special extra: Reactive Programming workshop with Erik Meijer!

Monday, February 17, 2014

Java 8 Lambdas - The Unintentional Puzzle

I was tinkering with Java 8 lambdas just lately. It happened to be an early morning on a bus from Tallinn to Tartu and I probably didn't sleep enough the night before. So I managed to puzzle myself with this little piece of code:

I actually expected it to print "Hello, lambda!" when executed, but it didn't. Can you figure out why? This is a very simple puzzler, and a very silly mistake that I did. I shouldn't have used the method reference to initialize the runner variable of RunForrestRun class. However, while the example is very simple, it actually shows that the new features do bring some accidental complexity into the language.

Wednesday, February 12, 2014

IntelliJ IDEA for Eclipse users

Finally! With help from the awesome RebelLabs team, I present you the Getting Started with IntelliJ IDEA as an Eclipse User report.

If you're an Eclipse user and considering to give IntelliJ IDEA a try - this is the finest read for you! If you're a convinced Eclipse (or NetBeans) user and not considering to switch to IntelliJ IDEA, still, you might learn something interesting from this report. If you are an IntelliJ IDEA fan, yet, you can find something interesting from this read.



Friday, January 10, 2014

Speaking at Jkofus 2014: Apples and Oranges

I will be speaking at Jfokus in Stockholm, on February the 5th. This is a fun talk again, about the IDEs. I'll be presenting the IntelliJ IDEA part along with Geertjan Wielenga (NetBeans) and Ken Walder (Eclipse).

Thursday, January 9, 2014

Tuesday, November 5, 2013

Automating IntelliJ IDEA Plug-in Development

In the previous post I wrote about managing the dependencies for IntelliJ IDEA plugin development and generating the project files. This was pretty simple and here's the full script:


apply plugin: "java"
apply plugin: "idea"

repositories {
    jcenter()
    maven {
        credentials {
            username 'username'
            password 'password'
        }
        url "http://my.repository.url
    }
}

dependencies {
    compile('org.zeroturnaround:jr-sdk:5.4.1') {
        transitive = false
    }
    compile 'org.ow2.asm:asm-all:4.1'
    compile 'org.slf4j:slf4j-nop:1.6.3'
    compile 'org.apache.commons:commons-compress:1.2'
}

defaultTasks 'setup'

idea.project.ipr {
    beforeMerged { project ->
        project.modulePaths.clear()
    }
}

idea.module.iml {
    withXml {
        it.node.@type = "PLUGIN_MODULE"
    }
}

task setup {
   description = "crete .idea based project structure"
   dependsOn ideaModule, ideaProject
   doLast {
     copy {
        from '.'
        into '.idea/'
        include '*.ipr'
        rename { "modules.xml" }
     }
     project.delete "${project.name}.ipr"
   }
}

task wrapper(type: Wrapper) {
    gradleVersion = '1.8'
}

The script is only limited to pulling down the dependencies from binary repository and generating the project files. However, one really big thing is missing here, is the SDK setup. Adding the new SDK for plugin development is simple enough, but I still have a good reason to automate that. In my plugin, there's a dependency on some SDK artifacts that are not included into SDK classpath by default. So adding the dependencies one by one into the SDK via the UI is a bit tedious and not really encouraging for the team work.

It would be cool if the script could register the IntelliJ Platform Plugin SDK and add it into the project files. It turns out that it should be doable as the SDK definitions are stored in options/jdk.table.xml file in IntelliJ IDEA's configuration directory.

It might be a bit brittle to go tinkering with the file directly, so maybe JPS API could actually be used to add a new entry for the SDK. (just an idea)

Those would be the steps for automating the setup:

  1. Fetch dependencies and generate .idea directory based project
  2. Generate Platform SDK entry to options/jdk.table.xml and add the reference to project *.iml file and .idea/misc.xml file
  3. Optionally, add more dependencies to Platform SDK definition
  4. The final step is the to add the build and release logic to the script

Now, a little bit of dreaming :-)

In the ideal world, the steps could be described as properties in build.gradle file:

  1. idea.module.type="PLUGIN_MODULE" - resolve as plugin module
  2. idea.project.sdk=auto (and idea.module.sdk=auto) - auto-generate the SDK entry (with good defaults) and add it to the project and module
  3. The extra SDK dependencies are probably something that needs a special care. Don't know what could be the best workaround, but maybe something like this:
    idea.project.sdk.dependencies {
       lib1.jar
       lib2.jar
       lib3.jar
    }
  4. Build script would basically mimic the autogenerated the Ant file, and release step actually requires a bit more than just changing the version of the artifact: the version in META-INF/plugin.xml has to be updated as well.

Dreaming aside, I think that the steps described above could be automated with a reasonable effort.

Sunday, October 27, 2013

Managing Dependencies for IntelliJ IDEA Plug-in Development

Probably the most painful part in developing plugins for IntelliJ IDEA is the dependency management of the libraries that your plugin might depend on. There is a multitude of problems that one may encounter:

  • IDEA binaries are not hosted publicly neither in Maven Central, JCenter, or any other repository.
  • Plugins cannot be built with the common tools like Maven or Gradle without setting up your hair on fire.

When your plugin depends on just a few external libraries, and the plugin build itself doesn't require customization, then everything is simple: put the dependencies into lib/ (or whatever) folder in the project and generate the Ant build script through Build -> Generate Ant Build... action. Simple. Well, not really simple: the generated build script will require a few JARs from IDEA by pointing to the IDEA installation directory. So the simplest thing to do in this case is to extract the full IntelliJ IDEA distribution into some directory at the machine where the continuous integration server runs.

Simple, ugly, but works. Why not to make things a bit more kosher?

In my world, any developer in the team should be able to clone the project, open it in the IDE(A), and ideally, launch the project without any additional tuning.

So what could we do in case of IntelliJ IDEA plugins projects? Store the *.iml files in VCS so that when the project is opened by another developer he would automatically have all the dependencies attached to the module? Not kosher.

For me, clearly, the dependencies should be managed by dependency management tool. Options: Maven, Ivy, Gradle. IDEA provides a very good Maven support. But not for its own plugin modules. In fact, for plugin modules I wouldn't even try to use Maven as once IDEA recognizes it as a Maven project, it will erase the information about its plugin origin.

Other options: Ivy and Gradle. Ivy is awesome. It works. There's also a nice plugin for IDEA that will automatically import the dependencies if it locates ivy.xml in the project directory. In that case you could still use the autogenerated Ant build script - just alter it a bit so that it would make a call to ivy task to get the dependencies and incorporate 'em into the build classpath.

Sounds a bit too hardcore to me. There's a high chance that the project import will not be as smooth as you would like it to be. Especially if the project structure isn't very trivial.

Gradle to the rescue!

Gradle is awesome when it comes to non-trivial project structures. Its Ant-like flexibility along with nice Groovy syntax and all the Maven-like goodies is just awesome!

First of all, managing dependencies is very easy. For instance:

  repositories {
    jcenter()
  }

  dependencies {
    compile('org.zeroturnaround:jr-sdk:5.4.1') {
        transitive = false
    }
    compile 'org.ow2.asm:asm-all:4.1'
    compile 'org.slf4j:slf4j-nop:1.6.3'
    compile 'org.apache.commons:commons-compress:1.2'
  }

The little cool part is that JetGradle (in IDEA 12) would also automatically resolve and add the dependencies into the project.

This is cool but it is not enough. First of all, JetGradle cannot import the project as an IDEA plugin module. Secondly, there's no JetGradle in IDEA 13 as Gradle integration is getting a major overhaul. OK, back to the drawing board.

There's an 'idea' plugin for Gradle, how cool is that?

Just run gradle idea and it will generate the project files, incorporating the references to the required dependencies. Good. But the generated module type is a Java module. And I need Plugin module. Have no fear, Gradle's here! We can easily customize the build script to adjust the XML project descriptor to our requirements.
  apply plugin: "idea"

  repositories { ... }
  dependencies { ... }

  idea.project.ipr {
    beforeMerged { project ->
      project.modulePaths.clear()
    }
  }

  idea.module.iml {
    withXml {
      it.node.@type = "PLUGIN_MODULE"
    }
  }

The withXml hook makes the magic here - instead of the auto-generated 'JAVA_MODULE' the final descriptor will contain 'PLUGIN_MODULE' which will make IDEA think that the module is an IntelliJ IDEA plugin.

Only little problem that bothered me: the generated project descriptor is an *.ipr file that is kind of deprecated. It would have been much better if the plugin generated a directory based project metadata. The feature request was filed long ago but still isn't resolved.

After experimenting with the project descriptors for a bit, I actually found a simple workaround for this minor annoyance. The .idea directory structure requires only modules.xml file that is identical to the *.ipr file that idea plugin generates. So I could just use this simple task to create directory based structure:

  task setup {
     dependsOn ideaModule, ideaProject
     doLast {
       copy {
          from '.'
          into '.idea/'
          include '*.ipr'
          rename { "modules.xml" }
       }
       project.delete "${project.name}.ipr"
     }
  }
[hate mode="on"]Just writing delete "*.ipr" would not work. That's annoying.[hate mode="off"]

So now I could just execute gradle setup and it would generate the directory based project structure, with the correct references to the required dependencies and I could import the project into IDEA without any hassle.

This is all good. However, this is not the end of the story! There's more to do and more issues to resolve:

  • Get the required IDEA internal artifacts to a local repository, so that these dependencies could also be downloaded via Gradle dependency manager.
  • Migrate auto-generated Ant build script into Gradle script.
  • Adopt the Gradle script to be able to manage the releases of the plugin.

However, [hate mode="on"]none of this hassle would be needed if IntelliJ IDEA provided a sane way of building the plugins and managing the dependencies.[hate mode="off"]