Uploaded image for project: 'Spring Roo'
  1. Spring Roo
  2. ROO-812

Op4J add-on to significantly reduce volume of Java code users have to write

    Details

    • Type: New Feature
    • Status: Resolved
    • Priority: Critical
    • Resolution: Complete
    • Affects Version/s: None
    • Fix Version/s: 1.1.3.RELEASE
    • Component/s: GENERAL OBJECTS
    • Labels:
      None

      Description

      Op4j (http://www.op4j.org/) offers some nice syntax improvements for Java programmers.

      I have done some experimentation with the output of "script vote.roo". I edited ChoiceIntegrationTest to create 12 votes across 3 different choices. The objective was to try out Op4j and compare the code sizes "before Op4j" and "after Op4j" for a simple collection-related operation.

      To this end, the following represents the Java syntax to iterate over a List<Vote> collection and produce a Map<Choice,List<Vote>> that groups the votes for each Choice:

      Map<Choice,List<Vote>> votesByChoice = new HashMap<Choice, List<Vote>>();
      for (Vote vote : votes) {
        List<Vote> currentVotes = votesByChoice.get(vote.getChoice());
        if (currentVotes == null) {
          currentVotes = new ArrayList<Vote>();
          votesByChoice.put(vote.getChoice(), currentVotes);
        }
        currentVotes.add(vote);
      }
      

      The above is 9 lines of code with normal formatting. With Op4j one can replace the above with a single line:

      Map<Choice,List<Vote>> votesByChoice = Op.on(votes).zipAndGroupKeysBy(Get.attrOf(Types.forClass(Choice.class), "choice")).get();
      

      However, two issues with the Op4j native code are (a) many new developers would consider that Get.attrOf(...) fragment a fairly complicated (and long) piece of code and (b) it's not type safe (the use of a "choice" literal).

      With Roo, we can simplify the code and also make it type safe, with all the nice code assist and literal-avoidance features we've come to expect in Roo apps. This works:

      Map<Choice,List<Vote>> votesByChoice = Op.on(votes).zipAndGroupKeysBy(Choice.Keys.CHOICE).get();
      

      Thus we've gone from 9 lines of type-safe, literal-free Java code (Raw java) to 1 line of type-safe, literal-free Java code (Op4j with Roo).

      To make this work I needed to produce 3 new compilation units, the contents of which are:

      public class ChoiceKeys {}
      
      privileged aspect ChoiceKeys_Roo_Op4J {
        public final Function<Object, Choice> ChoiceKeys.CHOICE = Get.attrOf(Types.forClass(Choice.class), "choice");
        public static final ChoiceKeys ChoiceKeys.instance = new ChoiceKeys();
      }
      
      privileged aspect Choice_Roo_Op4J {
        public static final ChoiceKeys Choice.Keys = ChoiceKeys.instance;
      }
      

      As usual the *_Roo_Op4J files are managed by Roo and thus are correctly maintained without user intervention. It would be preferable to have simply added a Keys inner type within Choice_Roo_Op4J, but this is not presently possible with ITDs. Andy Clement is looking into the latter. Once AspectJ offers this feature the code users have written will not require any changes, as the usage pattern for these inner types would be identical from an invocation perspective to the static final field model used above.

      It would be nice if we wrote a Roo add-on that made all of this tick. I'll attach my vote sample so anyone who wants to play with Op4j can do so. Just run the ChoiceIntegrationTest to see it in action and enjoy 1/9th the amount of code.

        Attachments

          Activity

            People

            • Assignee:
              sschmidt Stefan Schmidt
              Reporter:
              balex Ben Alex
            • Votes:
              5 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: