2

From what I have read most people either place command objects inside the controller (which I am not a fan of) or place them somewhere inside the src/groovy folder.

I, however, like how Grails has specific folders for controllers, domains, services, etc and was thinking it would be great to simply create a new source folder for command objects. Either /grails-app/commands or perhaps /src/commands. Having it laid out this way would help encourage the use of command objects.

I am a little concerned that doing this may break some grails magic that relies on specific project structure conventions. After running a few quick tests, I did verify that data binding and domain constraint importing still seem to function correctly.

Any thoughts or objections to this approach?

kjackson
  • 65
  • 7
  • Having a dedicated folder isn't a terrible idea. I place them within the structure of /src/ usually. – Joshua Moore May 15 '14 at 22:04
  • i wouldn't expect Grails to compile classes in `src/commands` or `grails-app/commands` so am surprised that this works. Personally, putting commands in their own package hierarchy in `src/groovy` provides sufficient separation for me – Dónal May 15 '14 at 22:23
  • Ideally it is placed inside `src/groovy` as @JoshuaMoore mentioned because it not a grails artefact that needs to go under `/gails-app/`. You just have to follow the convention of using `*Command.groovy`, using @Validateable, and generally speaking using the command object as an argument to controller action. That's it. – dmahapatro May 15 '14 at 22:24
  • 2
    @dmahapatro I'm fairly sure a command class can have any name, i.e. it doesn't need to end with `Command` – Dónal May 15 '14 at 22:26
  • You don't have to follow a convention of using *Command.groovy and you don't have to use Validateable. Both are optional. Only use Validateable if you want the thing to be validateable (many are not and don't need to be) and the source for the command object is defined outside of the source file of a controller which uses the class as a command object and you only need to use the *Command.groovy convention if you are using a not widely used feature that has to do with special parameter naming for data binding, which has been removed in Grails 2.4 in favor of a better option. – Jeff Scott Brown May 15 '14 at 22:28
  • @Donal Yes, I think so as well. I have been working with older versions where that was levied. I am sure that convention has changed. – dmahapatro May 15 '14 at 22:28
  • @Dónal you are correct. Command object classes can have any name (assuming it is a valid name per language restrictions... nothing to do with Grails or command objects) – Jeff Scott Brown May 15 '14 at 22:29

1 Answers1

6

Unlike top level Grails artifacts like domain classes, services, taglibs etc., the framework doesn't do anything special with command object classes. An exception to that is if they are defined within a controller source file for a controller which uses the class as a command object, in which case the compiler will automatically rig up the validateable stuff without having to mark the class with the Validateable annotation. If you are defining the command object class in its own source file then you will need the Validateable annotation if you want the thing to be validateable (not all command objects need to be made validateable). Given that, I don't think there is any benefit to having a special place to define these classes source files. The normal thing to do if they aren't defined in a controller source file is to define them under src/groovy/ and unless you have some good reason to deviate from that convention, you probably shouldn't.

Command object classes are almost special kinds of things in Grails, but not really. You can use anything as an argument to a controller action. You could use a class provided by Log4J as a command object if there was some reason to that. Having a special place to define them isn't really justified, IMO.

I hope that helps.

Jeff Scott Brown
  • 26,804
  • 2
  • 30
  • 47
  • Thanks. I did not realize that command objects have no special wiring behind them when defined outside of a controller. Good to know. As a side note: In one of your comments above you mention something to the effect of Grails 2.4 removing parameter name based data binding. If I am reading the documentation correctly it sounds more like they are expanding it such that you can have multiple command objects based on even more naming conventions (that being prefixing parameter names with the name of the object you want it bound to). – kjackson May 16 '14 at 01:14
  • The "Command Objects And Request Parameter Names" docs at http://grails.org/doc/2.3.8/guide/theWebLayer.html#commandObjects describe how this works in 2.3.x and the same section at http://grails.org/doc/2.4.0.RC2/guide/theWebLayer.html#commandObjects describes how it works in 2.4.x. In 2.3.x special parameter handling was associated with the name of the command object class. This was not ideal but it was kind of helpful. In 2.4 we are able to do some tricks at compile time so we can use the method parameter name instead of the type name, which is really a better solution. – Jeff Scott Brown May 16 '14 at 12:45
  • "I did not realize that command objects have no special wiring behind them when defined outside of a controller"... I am not sure what you mean by that, but I didn't say that. If "wiring" refers to autowiring dependencies from the Spring app context, that only happens to instances of command objects that the framework creates as args to controller actions. If you create one yourself, auto wiring does not happen. If that isn't the wiring you are talking about, then I don't know if I agree with your statement or not, depending on what "wiring" means there. – Jeff Scott Brown May 16 '14 at 12:52
  • I just simply meant that classes ending in "Command" receive no special treatment and that any other class used as a controller arg would function just the same. – kjackson May 16 '14 at 13:19
  • Yep. For 2.3.x the only difference in behavior between command object classes with names like *Command.groovy and any other command object class is the behavior described under "Command Objects And Request Parameter Names" at http://grails.org/doc/2.3.8/guide/theWebLayer.html#commandObjects. In 2.4.x there is no difference in behavior between command object classes with names like *Command.groovy and any other command object class. – Jeff Scott Brown May 16 '14 at 13:31