 So I'm going to talk about a tool chain that I've been developing along with Christian and Skulk who are here as well. The three of us are the entire JRuby Gradle team. It would be great to have other people join as well, but thus far it's the three of us. So let's hope we all get home safely. So most of the stuff that I do is open source work. That's kind of what I do in my free time. I garden a little bit, but I don't have pictures so I didn't really want to talk about it. I participate very heavily in the Jenkins project as well. I started the JRuby Gradle project last year at JRubyConf and you'll see why in a bit. I complain a lot on Twitter. I use a lot of foul language. You might not want to follow me. I'm not very polite. So during my day job, a lot of what I do is support developer tooling and infrastructure tooling on top of Ruby and the JVM. So at my employer lookout, a lot of what my team does is help us bridge the gap that a lot of companies in our, I would say, size tend to go through where you start out with rails, you start out with the simple MRI, the easiest thing possible, and then four years later you've got monorails running around and all sorts of different libraries and lots of problems with your tool chain. And a lot of what my team helps do is bridge the gap between the old world, which was MRI, and the new world, which is very JVM centric, sometimes with Ruby, sometimes with Scala, sometimes with Pure Java. But I say sponsored by because they did pay me to come out here. So I figured, download our appers, I don't know, whatever. So anyways, there's this problem with JRuby and for a long time it really bugged the, can I say bad words? Is that okay? Bugged the crap out of me. It's very upset about it when I first started to get really deep into JRuby that you can require a jar in JRuby and that adds that jar into the class path. And that's fun. But if you actually want to use that practically, it's very difficult to start to incorporate that native Java code into your application. Start mixing dependencies where maybe you don't want to build, you know, pull in Java code directly into your application, but you want to pull it into a gem and then pull that into your application. But also building your application, like how do you get to the point to where I've got Java code running around and I've got Ruby code running around and I need to produce my web application to deploy to production. And all of that I found to be very under supported in the JRuby ecosystem. There's some hacks that exist and I've seen and used all of these now and I've not been thrilled with any of them. The most common one is just to shell out to some other tool. I've seen so many projects more than I really wish to disclose where a rake task shells out to Maven or a rake task shells out to Ivy or a rake task God forbid shells out to Ant and Ivy. And that's how all of this Java code gets brought into a project. Another approach which was written by Christian is Ruby Maven. I personally have some strong objections to Maven as a tool chain, so this wasn't going to work for me. But then there's also Jbundler, which Christian also wrote. If any of you, just as a side note, have an opportunity and you've been using JRuby for a while, go thank Christian because I guarantee you've used more code of his than you actually realized. When I first started to really get into the ecosystem, everything that I started to use, Christian had wrote. So I'm very happy that he's working with the JRuby Gradle tool chain now. So Jbundler adds Java dependency resolution on top of Bundler. And that's useful, but that only gets you Java dependencies in your project. It doesn't get you building your Java code alongside your Ruby application. So there's this tool that I discovered through some coworkers called Gradle. Gradle is a polyglot build tool that's built by a company. I guess now they're called Gradle Inc. They're called Gradle Wear. It's an open source project. And I was first exposed to it through the Android ecosystem, where Android for a long time had this problem with build tooling to where they're very ant-centric, but that wasn't working. So people were building all these different hacks. So Google put a lot of effort into moving over to a Gradle tool chain and a company like Lookout being very heavily invested in the Android ecosystem also started to use Gradle. And it looked pretty neat. It's built around Groovy. There's a really useful syntax for configuring basic projects. There's a lot of useful built-in plugins. And it generally was a pretty good tool. So last year at JRubyConf, I was very frustrated in trying to build these polyglot projects with all of these sort of not mediocre tools, but tools that weren't really built for what I was trying to do. I needed something that was going to do my gem and jar dependency resolution. I need both of those in my world, because I'll have core libraries in jar files and I'll have Ruby libraries like Sinatra and gem files. I also need task and dependency management integration. And so what this means is for, let's say, building documentation for my application, I need a gem-like ASCII doctor. But I also need to run RSpec. With Bundler, RSpec and ASCII doctor both have to be present before you can actually boot up the application and do what you need to do. And so I wanted, you know, the ability to say, to run this task, I need these dependencies. And to run this other task, I need these other dependencies. So if you're only running one of those things, you only have to resolve and download dependencies for that one thing. I needed to be extendable. My job is building tools at Lookout, so being able to deliver tools to other developers is very important to me. And I also needed to be easy to manage. Sending out gems is okay, but getting everybody to make sure that the requiring gems in the rake files and using the right versions is fairly painful. And then there's some nice-to-haves as well of whatever tool that I would need to meet my needs. Being self-contained is pretty nice. One of the downsides that we have at Lookout is any given project might have its own version of Ruby that it relies on and some system dependencies that you might need. So developers have to rely on going through a checklist and a readme saying, you know, RVM install this thing and then apt-get-install these other libraries. And so I wanted all of that to be in one spot, if possible. And then having a lot of work to build on top of is pretty important. So I started building JRubyGradle, which is like the best thing to meet all of these needs. I think it does actually meet a lot of all the important features and the nice-to-haves, but it meets it with a couple different plugins. There's a base plugin, which is where everything sort of starts. And this has all of the foundational Ruby gem dependency management. It has a JRuby exec task for actually invoking JRuby. And it also has this nice handy little task called GenerateGradleRB. There's this sort of funny behavior with Gradle to where it likes to own the entire process and it likes to own standard in and standard out. So if you want to just run Ruby with pry, for example, it's very difficult to do that through Gradle. So we've got a task that lets you generate basically a bash script stub that uses the right class path, uses the right gem path, and invokes JRuby complete that way. There's this jar plugin, which we use heavily at Lookout, which basically supports the creation of library jars, which is just a bucket of, you know, jar dependencies and gem dependencies in one zip. And then, more importantly, for Lookouts use cases, self-contained executable jars. For a developer team at Lookout to deliver a piece of software, it is most ideal that everything that we can possibly pack into that archive is self-contained. So to deliver it, we don't have to go install Ruby on build machines, Ruby on production machines, and all these other things. So the JRuby jar self-contained executable jar actually packages in JRuby complete. It packages in another bit of code that Christian wrote called JRuby mains, which bootstraps the JRuby environment and then runs the Ruby application. And so the JRuby jar task actually allows you to take all of your Ruby Java code and produce a single jar file that will run all of that that you can take to any machine that supports or that's running JDK 7 or higher. There's a war plug-in. Don't use this. It's broken. I'm pretty sure it's broken. I haven't touched it in six months and we've changed a lot, so don't use it. Jars are better, anyways. There's a storm plugin. So last year at JRuby Comfy, you guys were talking about JRuby Gradle and Storm. Storm is a distributed message processing application in runtime environment. We use Storm very heavily at Lookout. And the Storm use case is actually what motivated the JRuby Gradle project in its entirety. Again, I don't know where Colin is. Colin's here somewhere. He's way back there. He wrote this library called Red Storm, which actually brings JRuby into the Storm ecosystem. And so the Storm plugin actually builds off of his work and packages up a topology jar, which is a slightly different looking artifact from a self-contained executable, so it can be deployed into a Storm cluster. There's a test plugin that we're working on right now, which will provide configuration for RSpec and Cucumber and MiniTest, I'm sure, eventually, and TestUnit, eventually, to where running these test tools from within Gradle will be a lot easier than it is today. Right now, we're using JRuby exec in a lot of places. And then there's also a very experimental rake task, a rake plugin that Skolk is working on to bring rake tasks out of a rake file and manifest them as Gradle tasks. There's a little bit of a chicken and egg problem here with how Gradle actually works and how it evaluates its Gradle scripts. But it's still interesting work nonetheless. So all this stuff's really neat. Everyone's eyes have glazed over. No one uses Gradle here. You don't understand why this is so valuable. So let's actually look at it. So I publish all of this to GitHub. It's just under our Tyler presentations. If you run this Gradle wrapper script, which is part of what is provided with the Gradle distribution, you don't need anything on your machine but the JVM and Git. And you clone this and you run Gradle W and you will build and run this presentation. Because this presentation, of course, is also using JRuby Gradle because it can be real. Let's do that. So I want to write some Ruby code. This is what this demo is about. And I want to write Ruby tests and I want to write Java code. And I want to use Ruby Gems and I want to use JavaJars. And I want to do all of this without burning out and being angry and needing to go have a drink. And so JRuby Gradle is going to help us do that. So this is some actual Gradle. This is all sourced from the demo project. So this is live code, I guess. There's a couple different things that go on in a Gradle file. Some of them are optional. Some of them are required. In this case, really what's important is this dependency closure. These curly braces are a closure in Ruby. But this dependency is closure. So I'm actually setting up a couple different dependencies for these different configurations. A configuration is just a bucket of dependencies and configuration. So for my JRuby exec configuration, because I just want to run some RSpec, I need to make sure that I've got RSpec actually pulled down. Inside of my jar, I want SLF for J because that's the simplest thing I could think of in terms of demonstrating calling out to Java code. So I've got gems to include this colorized gem. And the reason that these are defined in these different configurations is because gems is going to be pulled into the JRuby exec and the JRuby jar configurations. So Gradle allows you to sort of build supersets of dependencies, which is very useful for sharing dependencies between different types of behavior in your builds. I'm going to take a brief tangent and talk about how gem dependencies are actually resolved because I think this is very important as much as I don't like how it's being done currently. This is what we've got to work with. Gradle doesn't know how to talk to RubyGem repositories. The RubyGem repository format is its own special little snowflake. Nothing else uses it in the world except for RubyGems. So Christian actually wrote this library or this tool called RubyGem servlets, and it will take a RubyGem repository and present it as a Maven repository. And by presenting it as a Maven repository, now all of a sudden, not only can Maven resolve this, but also Gradle can resolve this, and any other build tool that knows how to talk to a Maven repository can all of a sudden, with the use of this proxy code, resolve RubyGem dependencies. And this is sort of the linchpin of how JRuby Gradle started to really come together. Otherwise, we wouldn't be able to pull in the RubyGem dependencies. So, yeah. Let's get back to executing some of our Ruby code. This is just a... This type of task is a JRuby exec. It's using RSpec, but ideally, once we get the test plugin further along, we have no need for implementing a spec task like this. Setting a group, a description. We've got a couple interesting things. The first bullet point is we're saying depends on classes. Now, classes is a task defined by the Java plugin, and so we're declaring a task dependency. So the only time that I'm actually going to be able to run spec is if all of my Java classes in this project can also compile successfully. When I'm executing this task, I want the class path from my main source set. So whatever was compiled, I want to be able to refer to at runtime when I run this JRuby executable. And then just basic RSpec stuff. Call RSpec and pass it this argument. And that's all I need to actually test my Java code and Ruby code with JRuby Gradle. This might be a little bit small, but the way that this actually works in practice when that script runs, it's going to do the same thing that RSpec does when you run it locally via RBM or RVM, in that it's going to have a custom gem home and a gem path set that's going to have all of your dependencies installed into it. In the case of JRuby Gradle, instead of going to your home directory.RBM slash gem sets, blah, blah, blah, all of this is actually contained within the build directory. So your dependencies are installed on a per project basis, so you can't share gem sets in the same way you would share gem sets with RBM. Some people might say that's a bug. I say that's a feature. I actually think it's very, very useful to have full isolation and full encapsulation, particularly in a CI context. At Lookout, we've had problems in the past where a Jenkins builder would have some corrupted gem set, garbage installed into a gem set in RBM, and then another build would come onto that machine and it would fail because it was using this sort of shared state outside of the Jenkins user's workspace. So installing all of this stuff into the build directory actually ensures that you've got isolation of the gems that you'll be referring to when you actually run your JRuby scripts. So the actual hybrid nature of this project, this is the demo code. I'm a pretty elite Java programmer. This is the most Java I've written in six years, I think. So this is about as good as I could get. So I just have a simple echo function that's going to take a string, log using slf4j that it's going to return a string, and just formats the string to send it back out. This is it. It's amazing code. And then I've got some Ruby code that's going to make use of that. There's some things if you're already familiar with JRuby, then you know what these do already. But if you're not, up at the top we require Java. I actually don't know if that's required anymore or not. But then we do a Java import of this string. And all this does is it brings the class demo into the current scope, which is useful because I don't like referring to com.github.artiler.presentations.blah every time I want to call a method. Just say where we're running, what version of Ruby, what version of the Ruby platform. We're going to create a Ruby string, and then we're going to print out that Ruby string. But we're going to pass the Ruby string into the Java class. It's going to give us a string back out, and then we're going to call .green on it. And .green is a method monkey patched onto Ruby string from the colorized gem. So we're sending a Ruby string in, we're getting a Java string back, and then we're doing Ruby things with it, which I think is pretty neat. I'm going to go one step further. I'm going to package this up as an executable that I could then give to someone else to run. So I'm going to use the jar plugin as well. And with the jar plugin, all I really need to do is say where to get some code from. The JRuby jar plugin, excuse me, depends on the jar plugin or jar task which is already defined in Gradle. So building on top of everything that they have there is pretty useful. And then we add a couple attributes onto the jar configuration. The notable one here is number two. This init script. What init script is for is just to say, when you execute my jar file, run this script. So this is effectively the main or the entry point for the JRuby runtime when it comes up and it starts executing. And then of course we're going to depend on the spec task. So spec depends on classes. So I've got to be able to build all my Java code to run this. Our actual jar task depends on spec, so I've got to be able to pass all of my tests first and then provided all of that works together, I get a jar artifact that will be produced at the end of this that I can then take and run anywhere I want to run. And then this is it running. And I'm using Colorize, which when you copy and paste strings into just a text block, it doesn't really work. So that's what it actually looks like when I plan on that. But you can see way up here, I can't really zoom in on this. You see way up here I'm sending a message in, this is a puts, and then I've got this slf per j log line, and then we've got a green string, which doesn't look very good on this projector. But this is the code going into Java code coming back out and being messed with with Ruby. And all of that is easily managed through JRuby Gradle, which I now feel confident as a Ruby developer building more Java code and integrating more heavily with the Java ecosystem. And for me personally, this actually gives me a very good way to go to other developers, whether inside of Lookout or outside of Lookout, and play to the strengths of Ruby as a language while giving them the ability to pull in some of the strengths of other tools and other languages that are out there. So in some of our applications if you're familiar with Kafka, it's a distributed message queue or distributed commit log technically. It's similar to ActiveMQ or RabbitMQ from a functional standpoint. We use that internally, but they distribute libraries that are built with Scala. So for our projects, I need to pull in Scala dependencies to interact properly with Kafka. And if I want a storm topology, storm is written in closure, if I want a storm topology to work with our Kafka cluster, I need to pull in closure code, I need to pull in Kafka code, I need to pull in other JVM-based dependencies, Java code, and then my Ruby code. And we actually have all of this being built, deployed, and executing right now based off of the JRuby Gradle toolchain at Lookout. And so compared to my frustration last year with not having any viable tools to really do this, I now have this avenue to where I can very easily take whatever is the best from the JVM and pull it in very easily to my Ruby projects and stay sane while building it. So I want to cover a couple advanced topics. These are more Gradle advanced topics while I'm here because I think they're important to know about when you think about what makes Gradle so powerful. One is this notion of a multi-project build. So if you look at the presentations, the presentation for JRubyConf is a project, or it's a multi-project project rather. There's one build.gradle in the root directory that calls subprojects, one being the example, and those build configurations are defined in each subproject. So in JRubyGradle's case, for example, I've got the base plugin, the jar plugin, and the warp plugin all built and tested at the same time. You can build and test one subproject at once if you want to, but you can also work with the whole slew of projects together, which is very, very nice. And then there's the built-in support for dealing with Java, the Java ecosystem, basically. Publishing Java artifacts is something that previously we have just built really crappy gems to publish a jar file from one host to another. But there's this Maven plugin in Gradle as is to where if you generate a jar file, you can just use the Maven plugin to deploy that to some Maven repository. So in our case, when we're building these JRubyJars, we're then using tools that already have been built and are used within the Java ecosystem to publish those back into a Maven repository for other tools to consume, which I think is neat. To publish a gem, you kind of have to hack around it. This is something that will be coming in a future release, but right now if you need to call anything or you need to work with anything in the Ruby ecosystem, you can just fire up a JRuby exec. So when I need to publish gems for my JRuby Gradle projects, I just gem push the file, which works pretty well. So yeah, how am I doing on time? I want to make sure I take enough time. So this project started last year. The first commit was right after JRubyConf, and it's been a very exciting year. I did a lot of bad things before Skulk and Christian came along and told me how stupid that they were, and now it's improved dramatically. But the next year is looking like it's going to be very promising as well for the JRuby Gradle project in general. The test plugin is exciting to me because there's some interesting things that we can do in the test plugin to increase parallelism and to make better use of resources on a Jenkins machine or something like that. There's a class called Isolated Scripting Container in JRuby Core, which does a very good job of isolating the actual JRuby runtime environment. And if I can stand up as many scripting containers as you have cores on your machine, I can partition out your RSpec test or I can partition out your Cucumber features to where if you just plug your tests into JRuby Gradle, we can run them faster than what you would use currently just running RSpec with JRuby from RBM or something like that. Now, there are tools like Parallel RSpec, but those rely on forks, and they don't work very well in JRuby. So I see a lot of good things that we can do providing a better tool chain for testing with JRuby than what we have right now. There's also IDE integration. I don't know how many people have used IntelliJ before. It's a very good IDE, particularly if you're a Ruby developer, even more particularly if you're a JRuby developer, because you can debug in and out of JRuby and in and out of Java from your IDE. Right now with JRuby Gradle, this doesn't work, but there are tools that IntelliJ or JetBrains has put together that make building IDE integrations with their debugger viable, and so that's something that's on the roadmap for the next few months. And then a deeper integration with the Gradle ecosystem. There's a lot of tools that are developed. Skulk is a very accomplished Gradle plugin author. There's a lot of other plugins that we need to integrate better with, so we're declaring the proper outputs and inputs for all of our tasks, and you can incorporate a JRuby project into a Gradle build a lot easier. With the most recent release of Gradle that came out I think two or three weeks ago, Gradle 2.5, there's this notion of there's a continuous build concept in there. Similar to what we're familiar with in the Ruby ecosystem with Guard, Gradle now supports that. And so testing and making sure that JRuby Gradle gives you the same functionality with Gradle 2.5 as Guard might on MRI is something that's really interesting and something that we need to start to tackle. So yeah, this, I'm gonna blitz through this. This presentation is using JRuby Gradle, Hurray, blah, blah, blah. It's also using a lot of the Gradle plugins. So we're pulling in base, but we're also pulling in one of the plugins that Skulk implemented, but also the ASCII Doctor plugin. The presentation's all built in ASCII Doctor. Pulling in Hamel, because we need that. And then starting to tie all of these things together. So I didn't have to go look at Ruby presentation generators or come up with something on my own. ASCII Doctor already has a lot of support for building a DECJS-based presentation. So I just had to tie that together into one Gradle project. So one more thing. I was up until 1.30, 2 a.m. last night, finishing this up. I figured I would announce it while I'm here. Decided to go ahead and make the API stable. JRubyGradle 1.0 has been released. It's been a year. Figured we might as well do it. Everything's on JRubyGradle.org. It's fairly well documented. The documentation is, of course, all built with JRubyGradle. You guys, why not? And it also defaults JRuby9000. So you'll notice nowhere in any of these build scripts did we specify the JRuby version. You can. The JRuby version is optional. But one of the things that we decided to do very early on is default the latest stable version of JRuby with the JRubyGradle plugins. So with 1.0 we default to 9000, which means a lot of my screenshots of JRubyGradle running are now out of date. But if you go grab it, or if you go grab this presentation, the presentation's using JRubyGradle 1.0, you should be able to run 9000 and pull in Java code fairly easily. And if you have problems, I'll be here all weekend. Are there any questions about this that I could answer?