 Welcome. Good morning. I see that if you're in the room today here, you didn't get scared off by the word Java in the title of my presentation. So I work at Engine Yard on the JRuby team and I want to talk to you today about refactoring Java to Rails. So when we think about refactoring, usually we're talking about improving the design of existing code. And when we're doing a refactoring, we're thinking about making incremental changes to an application and changing the code but not changing the functionality anyway. And that's generally the approach that I'm taking. But if you think about refactoring, I don't know if any of you have read this book. It's a classic book, great information, but it really applies at a really fine-grained level of your code base. So there's no patterns for refactoring like introduce new language or extractor Rails controller. Those higher level refactoring aren't some things you typically think about. And so another question you might be thinking about in terms of what to do with a Java application that you want to use Rails for is, well, why would you even do that in the first place? You guys are sitting here at the Scottish Ruby conference and I probably don't have to convince you that using Rails is a good idea or using Ruby is a good idea. But for a mainstream Java programmer, why would they even want to do something like that? And there's actually a fellow, Matt Rabel, who gave a talk in Belgium last December about comparing various JVM web frameworks. And he actually had the foresight to include Rails in his comparison, even though Rails technically is a Ruby framework, it runs just fine on the JVM with JVM. And I'll just mention, up front JVM 1.6 is our latest release. It just came out a couple of weeks ago and it's probably our biggest release to date. It supports Ruby 192 and its support for Rails is better than ever. Rails runs pretty much without a hitch. If any of you are coming from pure Ruby applications to JRuby, there's some other considerations in terms of what you might need to do to change your application. I'm not going to talk about that today, but I actually have to have a talk at RailsConf next month that's going to focus on that topic. I don't know if any of you by chance will make it there, but you can maybe look online for details about that in the future. So I want to talk, again, to get you back to this idea of refactoring and how it fits in the realm of a Java application or a legacy application or an enterprise application. And to do that, I want to introduce a metaphor with the built environment, with architecture. That's maybe a little bit of a weird metaphor to make because typically with software it's very malleable. With buildings, you build it, it's done. There's not a lot of refactoring you can do. But I actually found a couple examples that I think would apply to this. So when I talk about enterprise software, I'm really talking about long running projects, legacy code bases, those are the kinds of things you think of. So it's code that's already really entrenched and it kind of feels a little stagnated. It feels hardened. It's resistant to change. And so the whole idea behind bringing Rails or Ruby into the mix here is to enliven the application and make it able to respond to change more quickly. So to get back to my architecture metaphor, I want to bring up, my first example, I want to bring up the Sagrada Familia in Barcelona. I assume maybe some of you have been to see this structure. I myself have actually not been there to Barcelona to see it yet, but hopefully within my lifetime I might be able to get there and see it finished. This building is, you know, obviously if you know the history of it, it's been in construction for I think about a century or so. And they still have at least a good probably 10, 15 years before they can even call it close to complete. And what's interesting about this building is just such a long running project, right? And so they have all these different façades on the building and they have scaffolding inside of the building to hold up the archways while they're building out new facades and new interiors. And just this, I mean, already, like even seeing the word scaffold, right, kind of makes you think of rail scaffolding right away, at least that's kind of the metaphor that I was thinking of there. So you have this building that has all these different faces on it it's gone through different phases of construction and you could kind of think of software being done in that same way, at least a long running software project where you're doing multiple things to the project and at various stages you might be working on pieces that are only loosely related to other pieces in the past, but you still have to bring them together somehow. Another example I have is this hotel in North Korea. I think it was construction started back in the late 70s or early 80s. It's a fairly ambitious project. I think it's like a 40 or 50 story hotel and it's a really odd shape. And I think back in the mid-80s or so, it's probably not surprising that the North Korean economy might tank and the construction stalled out. And so the things stood empty with the, it's a little bit hard to see in the screen, but it stood empty with no skin on it at all over here. And so this is a picture of what it looked like in 2005 and then only recently it was sort of the project restarted again. You can see they're starting to put a glass skin on the outside. And so for this example you can kind of think of a software project where it might have been mothballed for a while and then you need to pull it out and actually revive it again and actually do something to it. Another area that's interesting is this idea of a seismic retrofit. These are buildings that have been retroactively reinforced to withstand earthquakes and other natural disasters and that kind of activity. And this is a picture of a couple buildings in Berkeley, California where they've had these cross brace struts applied to the outside of the building to reinforce them because when they originally built the technology if it was standing earthquake wasn't what it was. And so later on technology progressed and they are adding these extra structures on the outside of the building. So I found that kind of interesting. And then my final example, this odd structure in Krakow is another sort of abandoned building that probably never will be finished. And yet it kind of stands as an eyesore on the Krakow skyline but actually it's been kind of repurposed recently by H&M and some other advertisers. They put these huge billboards on the side of the building. And so that's kind of example of well the project's kind of dead, it doesn't really do anything but maybe you can still do something useful with it. And so to kind of summarize all these I'll just kind of click through all them real quickly here. I mean I think I kind of gave you some idea of how each of these structures has sort of a history behind them various phases of construction and you can kind of draw parallels with software with building new parts of the applications scaffolding, reviving old projects. The size and retrofit is kind of almost like you could think of it in terms of like a security audit or you want to improve the security of an old application by adding and the Skeletor example with finding new uses for old code. And so all these areas are areas where you can add rails into an application and quickly spin out new features. And I'm going to show you today how you can do that without having this completely disturb your existing application. And so I have this repository on GitHub that I'm actually just going to pretty much step through today and I'll kind of have an extended demo and we'll just kind of browse through the code and I'll try to give you some examples of some of the things that I did in it. So the idea I have with this repository is it's basically a, it probably spans about 30 commits or so and it starts with a basic spring MVC application that uses hibernate. It's actually the spring PEC clinic if you've ever seen or heard that application which is a little bit generic and a little bit small. It's at least something I could work with and something that was readily available that I could use. So the other comment I have about my approach here today is that I'd like to be standing up here giving you sort of an experiential report about how I did this to a real-world application. I don't have that today but I do know of some people in the community who have done this and I just haven't convinced them to step forward and talk about it or we haven't put our heads together to say let's get the word out. So my main idea with this example today is really just to be sort of a clean room. If I were to do this here's how I do it and it's out here in a repository well documented step by step and the hopes is that people, you guys and others can go look at the repository and browse through it, browse through all the commits and learn about some of the things that I did to introduce Rails into a Java application so it can provide a way forward if you will. The prerequisites are pretty small and if you're already doing Java coding you probably have most of these. You might need to install JRuby if you don't have it. There's a number of ways you can do that. You can go to JRuby.org there's a download page. You can get it through RBM if you use RBM and then of course you just need Git because the project is in a Git repository. So the way I structured the refactoring was to do it sort of in three phases. I did a small, medium and large refactoring and the reason for this was to sort of give you different options for how you might proceed in your application. So if you want to just do a small amount of changes you don't really want to affect the existing structure of the application the way it's laid out, the project, the way it's built, those kinds of things you might just consider some of the things in the small refactoring. And then the medium refactoring builds on that and adds some more functionality in and starts to take over more of the old application. Then the larger refactoring actually goes full scale all the way to completely replacing the spring MVC parts with rails parts. So we're going to step through all three of those hopefully in the time we have here today. So windows got resized again so hopefully we can see that alright. So on the left side of the screen here you can see sort of the basic project structure. It's just a normal Maven Java application with a source and you have your Java code and your Web app code in here. So when you're doing a refactoring what's the one thing you really don't want to you don't want to be caught without when you're doing a refactoring would be some sort of a test suite. You want to be running that constantly and making sure that you're not breaking anything as you go along. And so my decision for which I chose to build out a small Cucumber set of Cucumber features that test the application through HTML unit to verify that the Web pages are all serving up correctly. But we can actually look at if you haven't seen the pet clinic application before. I should have it running here. It's very simple. It's got owners, veterinarians and pets and visits are the main entities in there and you can look at a list of veterinarians, search for an owner, look at an owner and look at the pets and how many times the pets have been to the clinic. So that's the basic functionality. There's not a huge amount of stuff here that needs to be replaced. So the first thing we want to do is I want to I want to change to my Cucumber. So what I'm doing here is I'm going to be just stepping through this Git repository here. This is a list of all the commits here. So the first thing I did is we have the Cucumber suite so I can actually run it. And so I've got the Cucumber suite set up to boot the Tomcat Web server using Maven. It'll stand by and wait for that to finish. It takes a few seconds. And then it'll run the Cucumber suite against it with HTML unit in sort of a headless browser mode. For me with Cucumber you know there's a bunch of different ways you can test Web apps with it and this is using the Capybara gem and Solarity which is a wrapper around HTML unit. And so I'm running the Cucumber features here and some of them are failing. That's because the way I wrote the Cucumber suite was in such a way that the only way you could find some fields in the form was through having label tags that didn't previously exist in the Spring applications. So I actually add those in here. So there's actually a revision here where we add these tags, label tags around the labels and that's what Capybara uses to find those fields so it can fill the form in. So if we switch the first thing I did another, so after I had the Cucumber suite completely green we'll just skip that for now because I'll be running Cucumber again several times here and you'll see it green eventually. The very next step after I had the Cucumber suite was to actually bring JRuby into the mix and it was actually very simple with a Maven project you just have to declare those dependency jars and JRuby has those available. And then I simply added a small amount of code inside of the Java application's Web XML file where you configure what servlets and context listeners and so on and so forth are in the web app. So when that's there let me just change to this one. So now the application is still running. So here's the application yet again but now if I go to this rack URL you can see I've put a little rack application that, a little lobster application that comes in the rack distribution so we've actually wired in JRuby here and it's serving a little rack application here and you can see the rack machine going here and the show errors rack middleware that's coming through here. So in one small step we haven't altered the rest of the application and we've introduced JRuby at a new endpoint inside of the existing app and now we can start to do some things at that endpoint. So next I'm going to actually switch to Sinatra and so if we look now in the application we have actually have a little app RB in here and here's a little Sinatra app that I'm now going to run in the web app. I'll have to restart it. Alright so now when we go back to our application we see this little Sinatra app was running and I added some code in the Sinatra configuration to include the Sinatra reloader gem which allows you to change the Sinatra routes and actions and views on the fly so I can do things like I can actually make changes to my app RB file and go back and refresh the browser and the changes take effect. So this is obviously demonstrating another aspect of working with Ruby or Rails is that quick feedback mode of operation. Okay so now we're going to actually start to modify the existing application and what I'm going to do is I'm actually going to go into one of the JSP's see this here. You can see that I'm going to go into the JSP's and I'm actually going to change one of these XML links to point to the rack application. And so the idea I'm kind of introducing here is that you could bring in something like Sinatra or some other lightweight Ruby framework and you could use that to implement maybe some services around your existing Java application. Of course you could also pull in Java libraries to do that as well but Ruby makes it nice to do that kind of thing to serve up web services to serve up JSON and so on. So let's try this. So I'm going to go back to the cucumber suite now and run it and there should be one failure and there's a failure. So what I have is a I believe it's in this cucumber feature here. This feature of the Vets page where you can view the veterinarian's list as an XML document and so this is the one that's failing right here. I believe it's this step right here. Oh it's the same. Then I should see an XML document. So we replaced the link. The link goes through to the Ruby application but because we haven't actually implemented the XML link yet, probably there's some error page being returned. And so going back to our Sinatra app we see that we'll have to add a route in here for that XML page and actually implement that. And so to do that you can actually go in here and the next commit in the repository implements the XML feed and I'm just using the link here to build out the XML document. There's a method in here called clinic that's getting called and this is actually a Java class it's actually in the pet clinic Java code. We can actually look at it over here. And this gets into how JRuby has really nice Java integration. So we have this clinic interface that we're pulling out of the spring context and the clinic has this getVets method right here to get the list of vets. And then in this directory I have a helper's class for spring and you can see here's the clinic method here and all it does is it gets a handle to the spring context and then kind of indexes into the spring context and pulls out the clinic object by name. You can see here on this line up here we're declaring the context by just pulling into the web application context and pulling out the spring context that gets stored in a particular place in the server context. I also have an interesting little helper up here I'm declaring these methods on the spring bean factory that allows me to use square bracket operator to do sort of the equivalent of a hash key look up into the spring context and treat it syntactically just like a hash map which is kind of nice. That's our vets.xml implementation and now if we go back and run this again that scenario should be fixed. So while that's running let's go back and kind of move along. Alright so we can kind of proceed in this manner. We can make small changes to the existing application that break a test and then fix that test and then just keep going step by step through the application. That's kind of what happens here. Eventually we get to the point where I've got here's the test suite running. So all the tests are passing now. So to take this, the smaller factor in search to logical conclusion let's collapse this back down. You can go back and look at our Sinatra app now. You can see I've added a couple more actions here. There's a JSON action and there's also another XML document below and I'm using builder and I've actually extracted the builder code out to separate Sinatra views to kind of clean this up a little bit. So I mean that's just more of an internal refactoring but it makes this code cleaner and easier to read and easier to maintain. So what I'm going to do is I'm going to go from here into the medium refactoring and the first thing I'm going to do in the medium refactoring is I'm going to change the mode for mode of operation for JRuby inside of the web app. So before it was running as basically a servlet at a particular endpoint in the application and I'm going to change that to this filter right here. So if you're familiar with the Servlet API you know that there's servlets and filters and filters are sort of analogous to rack middleware where you can kind of wrap filters around the request pipeline and intercept them at any stage. So moving this, the JRuby integration to use a filter means that we can intercept all the requests going into the application and we can decide which ones we want to handle. And so I have this class that I wrote which basically how it works is a request will come in and it will delegate that request to the Ruby code and allow it a chance to handle that request. If the Ruby code says nope I don't know anything about that it will throw back a 404 error or maybe some other kind of error and then the filter will turn on and say okay well the Ruby code didn't know what to do with it I'll just let the regular Java application handle it. And so what this will allow us to do is we can start to incrementally layer new Ruby actions on top of the processing application without having to disturb any URLs or anything in the application but we can start to implement them in Ruby and that will just automatically pick up. So after I've done this the first step I introduce is to go back to our Sinatra app and instead of saying get rack vets.xml I'm actually going to overwrite or replace the vets.xml path which is the same path that the Spring app application would normally expect to use. So if we do that well first of all if we do that now we've changed the URLs in Sinatra so the existing Spring app is still expecting to go to rack vets.xml for example so it's not going to work but in the following commit then actually that is the commit that I do it I must have lost that in here. Oh I did do it in this commit. Okay so in a previous commit what I did was sorry about the confusion here. In a previous commit in a previous commit I actually changed the URLs back first before implementing the new actions and then in another commit I implemented the new actions at the right place thus making the test run again. So it was again sort of a red-green refactoring step. So the next point in the new application that I want to go to is I actually want to switch from Sinatra to Rails I'm going to start to do some more heavy I don't know if I say heavyweight things but we want to start to build out the application in a larger fashion and just feel like Rails is a better way for organizing all the various routes. So you can see here now I've actually added some Rails guts into the mix here. The Rails application app directory in the config directory and then later on we can actually go and implement we're going to go back and move our Sinatra code over to Rails so I'll do that here. And now we can see that we have a we have some routes so we're adding the routes into the Rails application here and we have a controller some controllers for this as well. So you can see I've moved the XML and JSON handling code that was previously in the Sinatra application. I've moved it over here and you can see I'm using a Rails respond to block to do the format handling in the same action. Yeah so at this point I haven't actually changed the model layer of the Spring application at all so maybe I'll stop here and just show you that if we so at this point yeah that's a good question to point out. So the Spring application is still running inside the web app and I can access it like I showed you before by kind of reaching into the Spring context employing things out of it. And at this point we've been doing basically controller and view type stuff so of the MVC application MVC we've just been doing views and controllers and we're just keeping the model code completely as it is and I think that's probably a good model in general for this kind of application where you've got an existing body of Java code or probably has some business logic embedded in it and you probably don't really want to change it or wholesale rewrite that. And so this is just kind of showing how you're layering these on top so yeah so this is just I don't have anything specifically that says that this is coming from Rails but you kind of recognize things like the runtime header and the fact that there's application XML here and it's just running through the Rails and there's an index XML builder here that has that builder code in it. Alright so got a little over 13 minutes left here at this point I actually want to move some of the actual HTML views into Rails and so what I've done to do that is for example what I'm doing next is I'm introducing a new route. You can see at the bottom here I've actually added a root route which will make the welcome page of the app go through Rails this time and there's a welcome controller as well. It has an indexing method but it's not really doing anything yet. What I'm going to do is I'm actually going to take the contents of the JSP and just wholesale and move it over into the Rails app which doesn't make a lot of sense I mean so we have a if we look at the welcome we have a we have an index that's the finished version okay so what I wanted to show is that I'm starting to take some of the content out of the JSP's and for example putting it into the Rails application layout and I make one small modification and I just do that so that we can visually highlight that that a page is being served from Rails versus from the Spring MVC portion of the application. Let's show that here in a moment. Just waiting for the server to finish booting. Alright so as you can see this is what I was talking about. I added a new graphic just for the Rails portion of the application that says okay this page was served by Rails and I included that background image in the Rails version of the layout but the Spring layout remains without that so if I click into a page that's still served by Spring that one's actually served by Rails here too if I click into a page that's still served by Spring you can see the Rails image in the upper corner goes away so this is a visual reminder say okay well this page is still done by Spring but this one is actually served by Rails so this is an interesting thing here I have one page that's being served by Rails and it serves up this search box and if I go and then click and submit the form then it actually submits the form to the Spring side of the application and I think this kind of demonstrates the power of sort of segregating your application according to URIs and thinking in terms of pure paths and endpoints in the application and the fact that you can take a form and serve it from the Rails application and submit the form to Spring is I think that's kind of a powerful concept for demonstrating how you can just sort of incrementally change the application. I'm going to skip ahead now to the larger factory and the main crux of the large refactoring what I want to do is I want to actually move the, so you saw before how we had all these Rails code embedded down kind of deep down in the all this Rails code kind of embedded deep down in the guts of the project and it still has a sort of a traditional Java field to the structure of the project. Well what I want to do is actually pull that code out up to the top level and just make it a proper Rails project so we can use the Rails server, we can use Rails generators to add new features to the app, we can do anything in more Rails like development mode. And now you can see I've got, I took all this stuff out of the web app and instead now I have my, it's actually not up here yet, but yeah I haven't actually moved the code in there yet, but you can see now it looks more like a proper Rails app structure where you have app config, script, test, vendor, and that sort of thing. So now what we're doing is we're actually changing from running in a mode where we're running the app in an embedded Tomcat container, we're going to switch to running the app with the Rails server which is WebRick by default. So we're kind of moving more completely out of the Java web app space and into kind of a pure Ruby app space. But because we're still in JRB here we can still do Java things, but now we actually have to do, we have to do one thing ourselves now that we got for free from before and that's to actually boot the Spring, we have to actually boot Spring ourselves from within the web app because there's no, it's not that stuff that normally happens within the Spring context listener, but now we have to do that work ourselves. There's obviously no, you know, at least not today there's no plugin for Rails that boots Spring automatically for you, although you could possibly take this code and make one from it. So what I've done for that is config initializers, there is this Spring class here and you can see all it does is it adds some, it basically sets up the Spring class path XML application context and that's sort of a way in Spring of saying, well here's my Spring configuration files here, just boot this up finding those files on the Java class path instead of the normal Spring web app way of doing it. And you can see here I have the Spring application context files here and I just make sure that those files are on the class path, they'll get loaded up. Now the other big issue we have is that we have this big Spring application and if you look at the Maven project file for this, you're going to scroll down it, you're going to see all these dependencies log4j, Apache stuff, MySQL, Hibernate you have all these jar files, how are we going to manage this stuff? Well, we can actually just use Maven and make Maven go to work for us on this. I wrote a plugin that's in the latest version of JRuby that you can use today and what it does is you can see it here you just run a Maven command line to call out to this JRuby plugin that I wrote and it generates this script that we're looking at right here. So you're in a Maven project, you run this plugin and it generates a sort of a class path script for you. And you can see here it basically gives me a list of all of the all the jar files that belong to this project. And then I can actually just call that set class path not to set up the class path for me. So we can see that here. Now we should be able to do Rails server. And so here's the pet clinic app served up by Webrick completely within the JRuby process. I set up the logging for this so that there's actually you actually see the you actually see the spring goo, you actually see the spring guts when it boots up it goes into the separate log file so it doesn't clutter up the console when you're running tests but it's there if you want to look at it. So yeah, we have that basic application running now if you start to navigate into it I don't have all the actions implemented here yet. We started to implement some of the actions up to this point back in the meeting refactoring and then at some point I just decided well let's just go over to this other mode and now we'll just implement the remainder of the features of the app in the Rails way of working things. So I'll just have a couple minutes left here and I'll show you that one example of some of the neat things you can do once you get into the kind of really leveraging Rails in the application. What I've done is there's a in the app model in the app models directory now there's an owner rb and what we actually have in here is we have a model it's actually just the same owner Java class that we have from before you can see the very top line it says Java import you know our pet clinic owner class and then I simply reopen it on the Ruby side and I add a bunch more stuff in it so you can see I've added the active model stuff here I've added some validators for the owner and so we can actually take an existing Java class mix in active model and use it within Rails just as we would expect and it feels almost like an active record object I mean not quite but pretty close and I can just well I guess so this is where it starts to get into the more destructive amount of changes right because we're starting to put validation logic might be something that would have been in the Java layer before that we're now putting at the Rails layer so if you screw up your validations you could potentially be storing bad data but as far as with Hibernate be happy it's not I'm not sure what you mean not be happy in what sense yep yeah oh I see what you're saying yeah well so all these extensions that you see here only exist in the Ruby world like so if you think of there being two different worlds inside of the VM there's the Java version of the object and the Ruby version of the object is only seen by Ruby code so when you pass when you do something to this Hibernate object and you operate it on the Ruby side this code is there but when that object is operating back in Java world down in the guts of Hibernate it just looks like a regular Hibernate Java object right so you would have to actually make structural modifications down at the Java layer still and this goes you know pretty far into it the next step would be to say well do we want to stick with Hibernate at all we could just at this point we've got a shell of an owner model with all the logic that we need and we could almost go and replace it with actor vector and I think if your database is structured well enough you might even be able to do that and I've talked to some people who say say that they were able to actually have an existing Java model and an actor record model both talking to the same database table now I wouldn't recommend writing through both of those channels but you know maybe if you're reading through both of them that would work fine so I'm kind of out of time here I wanted to just point out and say that this is I encourage you to check out the repository if you're interested in this and check out the details and if you find them interesting let me know if they can be improved this is obviously only one way of doing it in fact there's some other people that are doing things along these lines LinkedIn is doing stuff with Ruby in their in their Java apps there's some videos on the Engine Yard site that talk about this a couple of people have also done these kinds of things before and then I just want to point out that I we just finished a JReview book and I actually have some copies downstairs you might have seen so check that out if you're interested and I'll be around for the rest of the day so please hit me up for questions. Thanks.