Chapter 6. Removing Roo

While we'll be sad to see you go, we're happy that Roo was able to help you in some way with your Spring-based projects. We also know that most people reading this chapter aren't actually likely to remove Roo at all, and are simply wondering how they'd go about it in the unlikely event they ever actually wanted to. If you have a source control system, it's actually a good idea to complete these instructions (without checking in the result!) just to satisfy yourself that it's very easy and reliable to remove Roo.

6.1. How Roo Avoids Lock-In

At the time we created the mission statement for Roo, a key dimension was "without compromising engineering integrity or flexibility". To us that meant not imposing an unacceptable burden on projects like forcing them to use the Roo API or runtime or locking them in. While it complicated our design to achieve this, we're very proud of the fact Roo's approach has no downside at runtime or lock-in or future flexibility. You really can have your cake and eat it too, to reflect on the common English expression.

Roo avoids locking you in by adopting an active code generation approach, but unlike other code generators, we place Roo generated code in separate compilation units that use AspectJ inter-type declarations. This is vastly better than traditional active code generation alternatives like forcing you to extend a particular class, having the code generator extend one of your classes, or forcing you to program a model in an unnatural diagrammatic abstraction. With Roo you just get on with writing Java code and let Roo take care of writing and maintaining the code you don't want to bother writing.

The other aspect of how Roo avoids lock-in is using annotations with source-level retention. What this means is the annotations are not preserved in your .class files by the time they are compiled. This in turn means you do not need the Roo annotation library in your runtime classpath. If you look at your WEB-INF/lib directory (if you're building a web project), you will find absolutely no Roo-related JARs. They simply don't exist. In fact if you look at your development-time classpath, only the Roo annotation JAR library will be present - and that JAR doesn't contain a single executable line of code. The entire behaviour of Roo is accomplished at development time when you load the Roo shell. If you also think about the absence of executable code anywhere in your project classpath, there is no scope for possible Roo bugs to affect your project, and there is no risk of upgrading to a later version of Roo.

Because we recommend people check their Roo-generated *_Roo_*.aj files into source control, you don't even need to load Roo to perform a build of your project. The source-level annotation library referred to in the previous paragraph is in a public Maven repository and will automatically be downloaded to your computer if it's not already present. This means Roo is not part of your build process and your normal source control system branching and tagging processes will work.

This also means that a project can "stop using Roo" by simply never loading the Roo shell again. Because the *_Roo_*.aj files are written to disk by the Roo shell when it last ran, even if it's never loaded again those files will still be present. The removal procedures in this chapter therefore focus on a more complete removal, in that you no longer even want the *_Roo_*.aj files any more. That said, there's nothing wrong with just never loading Roo again and keeping the *_Roo_*.aj files. The only possible problem of adopting the "never load Roo again" approach is that someone might load Roo again and those files will be updated to reflect the latest optimisations that Roo can provide for you.

6.2. Pros and Cons of Removing Roo

By removing Roo, you eliminate the Roo-generated source files from your project. These are inter-type declarations stored in *_Roo_*.aj files. You also remove the Roo annotation library from your project. This might be attractive if you've made a decision to no longer use Roo for some reason, or you'd like to ship the finished project to your client and they'd prefer a simple Java project where every piece of code is in standard .java files. Another reason you might like to remove Roo is to simply satisfy yourself it's easy to do so and therefore eliminate a barrier to adopting Roo for real projects in the first place.

Even though it's easy to do so, there are downsides of removing Roo from your project:

  • Cluttered Java classes: If the *_Roo_*.aj files are removed, their contents need to go somewhere. That somewhere is into your .java source files. This means your .java source files will be considerably longer and contain code that no developer actually wrote. When developers open your .java source files, they'll need to figure out what was written by hand and is unique to the class, what was automatically generated and then modified, and what was automatically generated and never modified. If using Roo this problem is eliminated, as anything automatically generated is in a separate, easily-identified source file.

  • No round-trip support: Let's imagine for a moment that you've written (either by hand or via your IDE's code generation feature) a toString() method and getter/setter pairs for all your fields. You then decide to rename a field. Suddenly the getter, setter and toString() methods are all in error. If you use Roo, it automatically detects your change and appropriately updates the generated code. If you remove Roo, you'll lose this valuable round-trip support and be doing a lot more tedious work by hand.

  • No optimisations to generated files: With each version of Roo we make improvements to the automatically-created *_Roo_*.aj files. These improvements are automatically made to your *_Roo_*.aj files when you load a new version of Roo. These improvements occasionally fix bugs, but more often provide new features and implement existing features more efficiently (remember eliminating engineering trade-offs and therefore maximising efficiency is a major objective in our mission statement). If you remove the *_Roo_*.aj files, you'll receive the code as of that date and you'll miss out on further improvements we make.

  • Loss of Roo commands: There are dozens of Roo commands available to assist you adapt to evolving project requirements. Next month you might be asked to add JMS services to your project. With Roo you just "jms setup". The month after you're asked about SMTP, so you just "email sender setup". If you've eliminated Roo, you'll need to resort to much more time-consuming manual configuration (with its associated trial and error).

  • Deprecated library versions: Because Roo automatically updates your code and has a good knowledge of your project, it's easy to always use the latest released versions of important runtime technologies like Spring and JPA. If you stop using Roo, you'll need to manually do all of the work involved in upgrading your project to newer versions. This will mean you're likely to end up on older runtime library versions that have bugs, fewer features and are not maintained or supported. With Roo you significantly mitigate this risk.

  • Undesirable architectural outcomes: With Roo you achieve team-wide consistency and a solution with a high level of engineering integrity. If developers are forced to write repetitious code themselves and no longer enjoy optimised Roo commands, you'll likely find that over time you lose some of the consistency and engineering advantages of having used Roo in the first place.

  • Higher cost: With the above in mind, you'll probably find development takes longer, maintenance takes longer and your runtime solution will be less efficient than if you'd stayed with Roo.

As such we believe using Roo and continuing to use Roo makes a lot of sense. But if you're willing to accept the trade-offs of removing Roo (which basically means you switch to writing your project the unproductive "old fashioned way"), you can remove Roo very easily. Don't forget when in doubt you can always defer the decision. It's not as if Roo won't let you remove it just as easily in six months or two years from now!

6.3. Step-by-Step Removal Instructions

The following instructions explain how to remove Spring Roo from one of your projects that has to date been using Roo. Naturally if you'd simply like to remove Roo from your computer (as opposed to from an existing project), the process is as simple as removing the Roo installation directory and symbolic link. This section instead focuses on the removal from your projects.

As mentioned above, a simple way of stopping to use Roo is to simply never load it again. The *_Roo_*.aj files will still be on disk and your project will continue to work regardless of whether the Roo shell is never launched again. You can even uninstall the Roo system from your computer and your project will still work. The advantage of this approach is you haven't lost most of the benefits of using Roo and it's very easy to simply reload the Roo shell again in the future. This section covers the more complete removal option should you not even want the *_Roo_*.aj files any more.

Please be aware that enhancement request ROO-222 exists to replace step 1 with a Roo command, and ROO-330 similarly focuses on steps 2 and 3. Please vote for these enhancement requests if you'd like them actioned, although the instructions below still provide a fast and usable removal procedure.

6.3.1. Step 1: Push-In Refactor

Before proceeding, ensure you have quit any running Roo shell. We also recommend you run any tests and load your web application interface (if there is one) to verify your project works correctly before starting this procedure. We also recommend that you create a branch or tag in your source control repository that represents the present "Roo-inclusive" version, as it will help you should you ever wish to reenable Roo after a removal.

To remove Roo from a project, you need to import the project into Eclipse or SpringSource Tool Suite. Once the project has been imported into Eclipse, right-click the project name in Package Explorer and select Refactor > Push-In Refactor. If this option is missing, ensure that you have a recent version of AJDT installed. After selecting the push-in refactor menu option, a list of all Roo inter-type declarations will be displayed. Simply click OK. AJDT will have now moved all of the Roo inter-type declarations into your standard .java files. The old *_Roo_*.aj files will have automatically been deleted.

6.3.2. Step 2: Annotation Source Code Removal

While your project is now free of inter-type declarations, your .java files will still have @Roo annotations within them. In addition, there will be import directives at the top of your .java files to import those @Roo annotations. You can easily remove these unwanted members by clicking Search > Search > File Search, containing text "\n.*[@\.]Roo[^t_]+?.*$" (without the quotes), file name pattern "*.java" (without the quotes), ticking the "Regular expression" and "Case sensitive" check-boxes and clicking "Replace". When the next window appears and asks you for a replacement pattern, leave it blank and continue. All of the Roo statements will have now been removed. We have noticed for an unknown reason that sometimes this operation needs to be repeated twice in Eclipse.

6.3.3. Step 3: Annotation JAR Removal

By now your .java files do not contain any Roo references at all. You therefore don't require the org.springframework.roo.annotations-*.jar library in your development-time classpath. Simply open your pom.xml and locate the <dependency> element which contains <artifactId>org.springframework.roo.annotations</artifactId>. Delete (or comment out) the entire <dependency> element. If you're running m2Eclipse, there is no need to do anything further. If you used the command-line mvn command to create your Eclipse .classpath file, you'll need to execute mvn eclipse:clean eclipse:eclipse to rebuild the .classpath file.

Roo has now been entirely removed from your project and you should re-run your tests and user interface for verification of expected operation. It's probably a good idea to perform another branch or tag in your source control repository so the change set is documented.

6.4. Reenabling Roo After A Removal

If you decide to change your mind and start using Roo again, the good news is that it's relatively easy. This is because your project already uses the correct directory layout and has AspectJ etc properly configured. To re-enable Roo, simply open your pom.xml and re-add the org.springframework.roo.annotations <dependency> element. You can obtain the correct syntax by simply making a new directory, changing into that directory, executing roo script vote.roo, and inspecting the resulting pom.xml.

Once you've added the dependency, you're free to load Roo from within your project's directory and start using the Roo commands again. You're also free to add @Roo annotations to any .java file that would benefit from them, but remember that Roo is "hands off by default". What that means is if you used the push-in refactor command to move members (e.g. fields, methods, annotations etc) into the .java file, Roo has no way of knowing that they originated from a push-in refactor as opposed to you having written them by hand. Roo therefore won't delete any members from your .java file or override them in an inter-type declaration.

Our advice is therefore (a) don't remove Roo in the first place or (b) if you have removed Roo and go back to using Roo again, delete the members from your .java files that Roo is able to automatically manage for you. By deleting the members that Roo can manage for you from the .java files, you'll gain the maximum benefit of your decision to resume using Roo. If you're unsure which members Roo can automatically manage, simply comment them out and see if Roo provides them automatically for you. Naturally you'll need the relevant @Roo annotation(s) in your .java files before Roo will create any members automatically for you.

A final tip if you'd like to return to having ITDs again is that AJDT 2.0 and above offers a Refactor > Push Out command. This may assist you in moving back to ITDs. The Edit > Undo command also generally works if you decide to revert immediately after a Refactor > Push In operation.