Introduction to the DTO plugin

Data transfer objects: you either hate them or you loathe them. They give off that kind of smell that sets the alarm bells ringing and has you reaching for the disinfectant. DRY? Sorry, not today m’am. Let’s face it, anything that has you duplicating fields and performing straight copies between objects is deeply suspicious.

Despite that, DTOs still persist (pardon the pun). When you want to serialise data over RPC, they’re often one of the few options available to you. GWT-RPC is a case in point, and the reason for the Grails DTO plugin. Gilead allows you to transparently serialise Hibernate domain instances, but this only works if the domain class can be loaded by the client. Since GORM domain classes are typically Groovy, that’s not an option with GWT. Your typical Grails domain class also includes a bunch of stuff that the client is hardly going to be interested in, like the custom mappings. So we need a set of Java classes that the client can access – in other words, DTOs.

So what are the main issues with DTOs? First of all, you have to write them. In fact, you pretty much end up duplicating your domain classes! There’s little that’s more depressing. Second, you have to write code to copy the data from your domain instances to DTO instances. When done manually, this can be particularly error-prone as well as laborious.

What if we can mitigate those issues? That’s what the DTO plugin is for. It provides two features that can eliminate the labour involved with creating and maintaining DTOs. Let’s look at the first one.

Creating DTO classes

Your average DTO class is a copy of its corresponding domain class, minus all the mapping information and non-transient data. So the plugin provides a command that does this for you:

grails generate-dto org.example.MyDomain
The above will not only create a MyDomainDTO class for you that has the same persistent fields as MyDomain, but it will also create DTO classes for all related classes, such as those declared via hasMany or belongsTo. In fact, if you’re not careful you can end up with DTOs for your whole domain model!

Alternatively, if that’s what you want (DTOs for your whole domain model), then you can use

grails generate-dto --all
More control can be exercised with the --non-recursive option, which disables the default behaviour and means that the command will only create DTOs for the named domain classes. In other words, it doesn’t follow the relations.

Of course, once you have generated the DTO classes, you don’t have to stop there. If you want to limit the amount of information that will be transferred to a client, simply edit the classes and remove any fields or relationships you want. Or replace relations with a different field. For example, you may not want to return a whole user object associated with a blog post, but you might want to send the user ID or the username.

Generating the DTO classes is only half the story, though. You have to actually convert the domain instances returned by queries and the like into DTO instances.

Converting domain instances to DTOs

It’s possible to do the conversion manually if you want. You could even use Apache Commons or Spring to copy the fields from one object to another. But why? The plugin makes it easy to do the conversion by applying some Groovy magic. Given a domain instance, simply use one of the following options:

def post = Post.get(somePostId)
def dto = post as DTO

// or
dto = post.toDTO()

The first option, as DTO, fits in nicely with the look and feel of Grails converters, but you do have to remember to import the grails.plugins.dto.DTO class. The second option doesn’t require the import, but doesn’t look quite as funky either.

With the soon-to-be-released version 0.1.2 of the plugin, you can also serialise collections and maps of domain classes:

def posts = Post.findAllByCategory("music")
def dto = posts as DTO

That’s all there is to it. However, one thing to bear in mind is that things get more complicated if you edit the DTO classes. In such cases, you probably need to provide some custom mappings to ensure that the data is copied correctly. I’ve not tried it myself, but since the domain instance -> DTO mapping is done by Dozer, you should be able to provide a Dozer mapping file. Once thing I would like to add in future is easy custom mappings using Groovy instead of the Dozer XML files. ‘Til then, it’s XML I’m afraid.

For those people who find themselves in need of DTOs for whatever reason, I hope this plugin makes your lives just a bit easier. Happy coding!

48 thoughts on “Introduction to the DTO plugin

  1. John Rellis

    Hi Peter,
    Nice, I always thought I was doing something wrong having to copy the domain structure for the client. This seems like a must for GWT development. I tried out the plugin this morning and noticed a couple of things:

    Should the classes be generated in the client package so they are available to GWT? At the moment they are created in com.myApp.myDomainPackage in the java/src

    Secondly I have an enum as a property in a domain. It seems the plugin tries to create DTO’s for this too and an exception is thrown:

    Cannot get property ‘clazz’ on null object
    at GenerateDto$_run_closure1_closure3.doCall(GenerateDto:39)
    at GenerateDto$_run_closure1.doCall(GenerateDto:38)
    at gant.Gant$_dispatch_closure4.doCall(Gant.groovy:324)

    That be all!
    John

  2. Peter Post author

    Hi John,

    1. The DTO plugin isn’t just for GWT, so I didn’t want to make it do anything GWT-specific out-of-the-box. But it is an issue, yes.

    2. I’ll take a look. I have an enum in my own project, so I’m surprised I haven’t run into that yet.

    I have only just started using the DTO plugin with my GWT project today, and there is at least one problem worse than the above: GWT really doesn’t like the grails.plugins.dto.DTO class and creating a module for it is a pain. There are definitely plenty of kinks to work out, so there will probably be new versions of the GWT and DTO plugins by the end of next week.

  3. Steve Ardis

    Peter –

    Great plugin and looking to use it in a pure-services application(i.e. no UI) that will be exposed through the Grails Remoting plugin.

    This pure-services application will be used by another grails UI application, and probably something like Mule for handling integration traffic for message normalization and routing rules. My preference would be to expose only the DTO objects in the services layer, thereby leaving clients ignorant to domain objects and GORM/Groovy.

    Your plugin seems to be working great for finder methods, i.e. :

    class UserService implements UserServiceIF {
    static expose = [ “cxf”, “httpinvoker” ]

    boolean transactional = true

    UserDTO findUserById(long id) {
    User.get(id) as DTO
    }
    }

    But, I don’t see how to implement updates/creates using the DTO classes, i.e. :

    UserDTO updateUser(UserDTO user) {
    user.save()
    }

    This updateUser(..) obviously fails because “user” is not a GORM domain object. How do you covert the UserDTO to a domain object?

    I will admit to being new to both Groovy and Grails. So, if this is an ignorant question, I apologize. Or, is there a better way than using DTOs as an argument to the create/update methods that I am overlooking?

    Sorry for the long-winded question and thanks for any help you can provide.

    Steve Ardis

  4. Peter Post author

    @Steve As you’ve discovered, the plugin and it’s methods are currently geared towards the domain object -> DTO conversion. It’s possible to go the other way, but there are no special methods. Here’s how it might work:

    class UserService {
        // Inject the Dozer mapper
        def dozerMapper
        ...
        User updateUser(UserDTO userDTO) {
            def user = User.get(userDTO.id)
            dozerMapper.map(userDTO, user)
        }
    }
    

    However, this probably doesn’t work awfully well when it comes to relations. In fact, it will probably fall over, but I just don’t know.

    It may be possible to use the code that Grails has to map parameter data to domain objects, but it would be a fair bit of work and I personally don’t have a need for it yet.

    Hmmm…I’ve just thought: perhaps the code user.properties = userDTO.properties might work? I’m pretty sure it doesn’t handle relations, but it might do enough for you.

    Cheers,

    Peter

  5. Steve Ardis

    Peter,

    Curious why you thought your example wouldn’t work for relations.

    I was thinking about the following code and, from what I know about Dozer, it should have no problem going both ways:

    private addDtoMethods(final MetaClass mc, final ApplicationContext ctx) {

    // Then the fromDTO() method.
    mc.fromDTO = { Object dto ->
    return mapDTOInstance(ctx, dto)
    }


    }

    private mapDTOInstance(ctx, obj) {
    // Get the appropriate domain class for this DTO instance.
    def dtoClass = obj.getClass()
    def dtoClassName = dtoClass.name
    def domainClassName = dtoClassName.substring(0, dtoClassName.lastIndexOf(“DTO”))
    def domainClass = dtoClass.classLoader.loadClass(domainClassName)

    // Now convert the DTO instance to a domain object.
    def mapper = ctx.getBean(“dozerMapper”)
    return mapper.map(obj, domainClass)
    }

    This is untested and I’m not even really sure how to integrate this into your DtoGrailsPlugin.groovy file for testing. If I get some time, I’ll figure it out.

    Steve Ardis

  6. Peter Post author

    @Steve I’m simply unsure whether Dozer will update the domain objects and add new ones in a way that means the changes will be persisted correctly. It may very well work in most, if not all cases, but I just have a nagging feeling that Hibernate objects are a bit too different for it all to work smoothly. I hope I’m wrong!

    To test your fromDTO() method, add an integration test to either test/projects/default or test/projects/appWithConfig, or preferably both. Start with the default test project – you’ll find an integration test already there that tests the toDTO() method.

  7. marko

    >> Data transfer objects: you either hate them or you loathe them. They give off that kind of smell that sets the alarm bells ringing and has you reaching for the disinfectant.

    Is it any less smelly to tightly couple the business domain model to the UI (especially fat client UI’s)?

    The whole issue of interfacing the domain model to the presentation layer (similar to the issue of ORM’s in my opinion), is messy with no perfect solution i can see.

    Remoting the domain model to the UI seems great at first thought, and yes, maybe 80% of the UI model is similar to the domain model. But it’s that other 20% that can end up corrupting the domain model. Separation of concerns, loose coupling, these are ideas that are at least (if not more) important than DRY.

    But on the other hand, at least for smaller projects, the productivity gains of skipping DTO can be compelling.

  8. Peter Post author

    @marko While I mostly agree with you, I think you’re missing the fact that you can modify the DTO classes after you have generated them. The initial generation allows you to get off the ground quickly, but after that you can fine-tune the DTOs and exclude fields and relations that shouldn’t be visible to the clients. At that stage, you need to take advantage of Dozer’s mapping files.

    One day I hope to provide an easier mapping mechanism than the XML files, but they work for now.

  9. marko

    Sorry Peter, my comment was not a criticism of DTO’s/Dozer. On the contrary, i have a strong philosophical pull towards decoupling the UI and domain model. The only way to do this is through some form of DTO (my favored interpretation is REST documents). Of course the uncomfortable baggage that comes with a clean separation of models is some amount of repetition.

    My comments were more directed towards the perception that using the domain model as-is from a disconnected context (like a fat UI), is not only a preferable architecture to DTO’s, but is goal that tools should strive to enable.

    Personally i have been questioning myself for years, wondering what the right answer is to DTO vs direct domain model? My pure/simple side says “always REST” (or DTO), but my pragmatic/productivity-craving side is open to finding some mechanism to “transparently” operate on remote managed domain model objects. It’s always nice to get something for nothing, but at what cost does the immediate gratification come with?

  10. Peter Post author

    No worries. I pretty much agree with you on using a server-side domain model from a client. I prefer the decoupling enabled by DTOs and XML/JSON.

  11. Raj

    I am using the DTO plugin together with GWT plugin. When running in the hoted mode the GWT compiler complains that it can’t find grails.plugins.dto.DTO interface to compile the generated DTO classes. Is there a setting that I am missing? Are the plugin classes exposed to GWT?

    Thanks for your work.

  12. Peter Post author

    You need to include the DTO module:

        <inherits name="grails.plugins.Dto"/>
    

    You’ll need the latest snapshot of the GWT plugin (that I’ve just released) for this to work.

  13. Anders

    Hi Peter,

    Thanks for the plugin.

    I like toString() methods on the DTO’s. So I’ve added

    // toString()
    writer.write “\n\t@Override”
    writer.write “\n\tpublic String toString() {”
    writer.write “\n\t\tStringBuilder sb = new StringBuilder();”
    writer.write “\n\t\tsb.append(\”${dc.shortName}DTO[\”);”
    fields.each { field ->
    writer.write “””\n\t\tsb.append(“\\n\\t${field.name}: ” +
    this.${field.name});”””
    }
    writer.write “\n\t\tsb.append(\”]\”);”
    writer.write “\n\t\treturn sb.toString();”
    writer.write “\n\t}\n”

    just above

    // Class terminator.
    writer.write “}${eol}”

    in my local ~/.grails/1.2-M3/projects/mbservice/plugins/dto-0.2/src/groovy/org/codehaus/groovy/grails/plugins/dto/DefaultGrailsDtoGenerator.groovy

    Maybe you could add it to the official plugin?

    Best
    Anders

  14. Natraj

    I’m running grails 1.1.1, and I just downloaded the dto plugin ( using the grails plugin command).
    I’m still having the issue another user had when my domain class has a reference to an enum.
    there are several more issues.. when I use the –all and –pkg arguments, it seems to create classes inside .true, and the classes just have a package declaration called ‘true’.

    Should I upgrade to a grails 1.2 M build?

    thanks
    Natraj

  15. Natraj

    More on the enum problem:
    Initially, my enum was under src/groovy. After having the “Cannot get property ‘clazz’ on null object” error, I tried putting it under
    src/domain
    That did a little better in terms of generating the class referring to the enum, but since it couldn’t generate the DTO corresponding to the enum, the code wouldn’t compile.
    Next, I tried changing the enum to a Java enum, and putting that under src/java.
    Again the “Cannot get property ‘clazz’ on null object” error.

    thanks,
    Natraj

  16. Peter Post author

    @natraj The “true” issue is specific to Windows. We could really do with some committers who use that platform because we’re all Linux/Mac OS X. Unfortunately there’s no workaround at the moment.

    As for enums, could you please raise a JIRA issue with a reproducible example? Thanks.

  17. Natraj

    One other question:
    I pulled the DTO plugin using the grails command – and it shows that the plugin version is 0.2.2
    With this, the GWT (1.7) seems to be having trouble with the declaration.

    When I try the ‘gwt-compile’ command, I see this error:
    Compiling GWT modules …
    Module: com.episoft.PatientInfoScreen …
    [java] Loading module ‘com.episoft.PatientInfoScreen’
    [java] Loading inherited module ‘grails.plugins.Dto’
    [java] [ERROR] Unable to find ‘grails/plugins/Dto.gwt.xml’ on your classpath; could be a typo, or maybe you f
    orgot to include a classpath entry for source?
    [java] [ERROR] Line 2: Unexpected exception while processing element ‘inherits’
    [java] com.google.gwt.core.ext.UnableToCompleteException: (see previous log entries)
    [java] at com.google.gwt.dev.cfg.ModuleDefLoader.nestedLoad(ModuleDefLoader.java:225)
    [java] at com.google.gwt.dev.cfg.ModuleDefSchema$BodySchema.__inherits_begin(ModuleDefSchema.java:212)
    [java] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

  18. zyro

    i came across a problem mapping my domain class(es) to the dozer dtos: dozer or the dto plugin have no options to limit the “mapping depth”… it just initializes any hibernate proxy or collection it finds in the whole object graph that is to be mapped.
    now i have got a db schema respectively domain class associations that result in the whole database being sqeezed out by dozer because it just “does not stop”.

    any common workaround here? a similar dozer feature request to make a “depth-limit” parameter available in dozer seems to be stuck since mid 2k8 πŸ™

    zyro

  19. Lik

    Hi Peter,

    I have also encountered the same error as Natraj and I installed the GWT plugin 0.5-SNAPSHOT thru the grails install-plugin command.

    The Dto.gwt.xml file seems missing in the plugin source.

    Lik

  20. Peter Post author

    I’ve just installed the plugin into a fresh application and verified that the DTO module file is here:

    ~/.grails/1.2.0.BUILD-SNAPSHOT/projects/gwt-app/plugins/gwt-0.5-SNAPSHOT/src/gwt/grails/plugins/Dto.gwt.xml

    Are you sure it’s not there? If it’s not, what platform are you running on? Maybe it’s something platform-specific.

  21. Lik

    Hi Peter,

    I am using grails 1.1.2 on Mac OS X. I have verified that the Dto.gwt.xml is also in my plugin source folder. It seems that grails 1.1.2 could not find the gwt plugin source under the src/gwt folder.

    The problem has been resolved after I upgraded to 1.2.0.RC2.

    Many thanks for you help.

    Lik

  22. Don

    Hi Peter,

    I’m using grails 1.2.0, dto plugin 0.2.2 and gwt plugin 0.4.1 on Mac OSX. When I run grails generate-dto I get a NullPointerException :

    grails generate-dto M1_user
    Welcome to Grails 1.2.0 – http://grails.org/
    Licensed under Apache Standard License 2.0
    Grails home is set to: /Users/don/Desktop/grails-1.2.0
    Base Directory: /Users/don/Desktop/grails-1.2.0/GwtTutorial
    Resolving dependencies…
    Dependencies resolved in 2043ms.
    Running script /Users/don/.grails/1.2.0/projects/GwtTutorial/plugins/dto-0.2.2/scripts/GenerateDto.groovy
    Environment set to development
    Compiling GWT i18n properties files …
    Module: org.grails.gwttutorial.Application …
    No i18n Constants file found
    No i18n Messages file found
    Finished compiling the i18n properties files. …
    Compiling GWT modules …
    Finished compiling GWT modules …
    Compiling GWT i18n properties files …
    Module: org.grails.gwttutorial.Application …
    No i18n Constants file found
    No i18n Messages file found
    Finished compiling the i18n properties files. …
    Compiling GWT modules …
    Finished compiling GWT modules …
    Error executing script GenerateDto: java.lang.NullPointerException: Cannot invoke method replace() on null object
    gant.TargetExecutionException: java.lang.NullPointerException: Cannot invoke method replace() on null object
    at gant.Gant$_dispatch_closure4.doCall(Gant.groovy:331)
    at gant.Gant$_dispatch_closure6.doCall(Gant.groovy:334)
    at gant.Gant$_dispatch_closure6.doCall(Gant.groovy)
    at gant.Gant.withBuildListeners(Gant.groovy:344)
    at gant.Gant.this$2$withBuildListeners(Gant.groovy)
    at gant.Gant$this$2$withBuildListeners.callCurrent(Unknown Source)
    at gant.Gant.dispatch(Gant.groovy:334)
    at gant.Gant.this$2$dispatch(Gant.groovy)
    at gant.Gant.invokeMethod(Gant.groovy)
    at gant.Gant.processTargets(Gant.groovy:495)
    at gant.Gant.processTargets(Gant.groovy:480)
    Caused by: java.lang.NullPointerException: Cannot invoke method replace() on null object
    at GenerateDto$_run_closure1_closure3.doCall(GenerateDto:95)
    at GenerateDto$_run_closure1.doCall(GenerateDto:94)
    at gant.Gant$_dispatch_closure4.doCall(Gant.groovy:324)
    … 10 more
    Error executing script GenerateDto: java.lang.NullPointerException: Cannot invoke method replace() on null object
    Application context shutting down…
    Application context shutdown.

    Any suggestions?

    Thanks,
    Don

  23. Barton

    Hi,

    Just starting to learn Grails so maybe I’m missing something with how to run DTO.

    From my root I entered:

    grails generate-dto –non-recursive Actor

    And got the following stack trace:

    Error executing script GenerateDto: java.lang.NullPointerException: Cannot invok
    e method replace() on null object
    gant.TargetExecutionException: java.lang.NullPointerException: Cannot invoke met
    hod replace() on null object
    at gant.Gant$_dispatch_closure4.doCall(Gant.groovy:331)
    at gant.Gant$_dispatch_closure6.doCall(Gant.groovy:334)
    at gant.Gant$_dispatch_closure6.doCall(Gant.groovy)
    at gant.Gant.withBuildListeners(Gant.groovy:344)
    at gant.Gant.this$2$withBuildListeners(Gant.groovy)
    at gant.Gant$this$2$withBuildListeners.callCurrent(Unknown Source)
    at gant.Gant.dispatch(Gant.groovy:334)
    at gant.Gant.this$2$dispatch(Gant.groovy)
    at gant.Gant.invokeMethod(Gant.groovy)
    at gant.Gant.processTargets(Gant.groovy:495)
    at gant.Gant.processTargets(Gant.groovy:480)
    Caused by: java.lang.NullPointerException: Cannot invoke method replace() on nul
    l object
    at GenerateDto$_run_closure1_closure3.doCall(GenerateDto:95)
    at GenerateDto$_run_closure1.doCall(GenerateDto:94)
    at gant.Gant$_dispatch_closure4.doCall(Gant.groovy:324)
    … 10 more
    Error executing script GenerateDto: java.lang.NullPointerException: Cannot invok
    e method replace() on null object

    The Actor.groovy (no package) class is:

    class Actor {

    static belongsTo = Film
    static hasMany = [films: Film]

    String firstName
    String lastName

    static constraints = {
    firstName(nullable: false, blank: false, maxSize: 45)
    lastName(nullable: false, blank: false, maxSize: 45)
    }

    static mapping = {
    id column: “actor_id”
    films joinTable: “film_actor”
    sort lastName: “asc”
    version false
    }

    String toString() { “${firstName} ${lastName}” }

    void setFirstName(String firstName){
    this.firstName = firstName?.toUpperCase()
    }

    void setLastName(String lastName){
    this.lastName = lastName?.toUpperCase()
    }
    }

  24. Peter Post author

    Despite having a plethora of tests, none of them actually tested domain classes with no package – doh! This has been fixed in version 0.2.3 of the plugin.

  25. Alberto

    Hi, I’m writing a tutorial on GWT on Grails using the DTO plugin (previously I did one without using it), after executing “grails generate-dto” the generated DTO implements grails.plugins.dto.DTO, but that has not been imported or anything else in my project.
    I found that it is a simple interface residing deep in ./.grails/1.1.2/, so the question is: do I have to copy paste this in my project the first time to have all working properly or am I doing something wrong and that’s why I do not see “by default” this interface?

    Thank you in advance and for the plugin πŸ˜‰

    Ciao

  26. Peter Post author

    @Alberto You have to inherit the DTO module:

      <inherits name="grails.plugins.Dto"/>
    

    I also have these set up as source paths:

      <source path="client"/>
      <source path="shared"/>
    
  27. Alberto

    Thanks for the quick reply.
    Yes, I did the inherits part, yesterday I saw you said that to another user, but that did not solve my problem, which is: I do not have the DTO file in my project. You set those source paths, ok, but where did you put the class? I do not have a “shared” path, do I have to put DTO.java inside a folder of my choice and then link it with ?

  28. Peter Post author

    What version of the GWT plugin are you using? Do you have the DTO plugin installed (I assume yes based on the fact you found the DTO source file)? Are you running into problems when doing grails compile or grails compile-gwt-modules?

    The GWT plugin (depending on the version) should check whether the DTO plugin is installed and if so, add its src/java directory to the GWT compiler classpath.

  29. Alberto

    Sorry for the delay, I was at work and I don’t have my stuff there.
    GWT plugin at version 0.4.1, yes I have installed the DTO plugin, which is at version 0.2.3.
    No problems during compile in each of the two.

    It’s not doing that… what can I do to solve this? Copy paste the DTO interface into src/java?

  30. Peter Post author

    You need version 0.5 of the GWT plugin. Alternatively, patch the scripts/_GwtInternal.groovy file to include:

                // Must include src/java and src/gwt in classpath so that
                // the source files can be translated.
                if (new File("${basedir}/${gwtSrcPath}").exists()) {
                    pathElement(location: "${basedir}/${gwtSrcPath}")
                }
                pathElement(location: "${basedir}/${grailsSrcPath}")
                pathElement(location: grailsSettings.classesDir.path)
    
                // Add the plugin's module paths.
                pathElement(location: "${gwtPluginDir}/${gwtSrcPath}")
                pathElement(location: "${gwtPluginDir}/${grailsSrcPath}")
    
                // Add the DTO source path if that plugin is installed in
                // the current project.
                if (getBinding().variables.containsKey("dtoPluginDir")) {
                    pathElement(location: "${dtoPluginDir}/${grailsSrcPath}")
                }
    
  31. Alberto

    I had no luck upgrading in my previous project: I upgraded the gwt plugin to 0.5 and then run grails install-plugin dto. I still don’t have the DTO interface.

    I created a new project and run:
    grails install-plugin gwt
    grails install-plugin dto
    …and I still don’t have the DTO interface.

    I’ll try the patch way, but I’m confused, there must be something wrong I’m doing here…

  32. Alberto

    Ok, thanks to Peter that solved my problem, I was using Springsource Tool Suite, I just had to make a Grails Tools -> Refresh Dependencies.
    I’ll write a tutorial on this with all the tips. Thanks again.

    Ciao

  33. ados

    hi,

    i have a grails web app and a grails plugin which houses all the domain classes and services that sit on top of these. I have changed the services to return DTOs using the plugin. However , i seem to have to install the dto on the client side (the web app) too, surely i should have to do this ?

    Anyway I installed it on both sides, now I am getting a stackoverflow error when i try to do a tostring on my userDTO as it has roleDTos attached to it which in turn has the same userDto attached to itself – so it goes round and round and bombs out. Is there a solution to this without having to exclude some dtos ?

  34. dave

    peter, i’m reasonably new to grails but have been working with GWT for a couple years. i’ve been using both your GWT and DTO plugins in getting going with grails, so first off, thanks for that. πŸ™‚

    probably because of my previous experience with GWT i’m used to a command pattern approach via GWT-RPC. been looking at your command pattern blog and now this one.

    what i wanted to ask is, what’s your preferred architecture for GWT communication with the server? i found the comment in one of your responses above:

    > No worries. I pretty much agree with you
    > on using a server-side domain model from
    > a client. I prefer the decoupling enabled
    > by DTOs and XML/JSON.

    right now i’ve got it working by using the command pattern approach with action handlers, with the action and response command objects wrapping DTO classes. but i’m just wondering if that’s the best way to go long term, and if a cleaner approach would be to use RequestBuilder (which i don’t have experience with) to call REST apis and render the responses from grails as JSON. i don’t know if i’m that excited about getting into javascript overlay types and all that in GWT, but it may just be best to bite that bullet and do it.

    so, just wondered if you could elaborate a bit on your comment about decoupling enabled by DTOs and XML/JSON and how you actually go about doing that.

    thanks!

    dave

  35. Peter Post author

    @dave I would ask on the grails-gwt Google group/mailing list. One or two people are using RequestBuilder with JSON responses and they say that’s the best way to go. I don’t have any experience with it myself, but it’s a more natural fit on the server side for Grails. I’m sure you can rejig the command pattern to work with JSON responses.

    Sorry, I haven’t done active GWT development for over half a year now and I wasn’t an aficionado in the first place πŸ™‚

  36. dave

    thanks peter. i found at least one discussion on the grails-gwt group on the topic and started to draft an email to see if i could get any more or new info out of anyone. (i’ve since gotten kind of distracted.)

    i’m now leaning towards RequestBuilder and JSON just so there is a clearer separation between GWT on the client and grails on the server. using the gwt plugin, dto, and action handlers it seemed to be getting mixed together a bit too much.

    whatever i end up doing i need to make sure that not only are the client and server loosely coupled, but also the code calling into that communication on both ends is also abstracted enough so if i decide to switch anything later it minimizes the risk.

    regardless, fun stuff. πŸ™‚

    thanks again.

    dave

  37. Srinivas

    Peter,

    Two questions:

    1. Once the DTOs are generated, if we remove few attributes (and getters/setters), and perform toDTO() at runtime, will it give Exception or only map the available fileds in DTO?

    2. We are currently doing DTO -> Domain objects using domain class constructor which takes DTO as input, and use this.s1=dto.getS1() methods.. This is writing lot of code in the constructor. Any short-cut here?

    Regards,
    Srinivas.

  38. Peter Post author
    1. To be honest, I don’t know. It depends on what Dozer does (the plugin uses the Dozer library to map the domain classes to DTOs). I think only properties that are common to the domain class and the DTO are copied across.
    2. I think you’re much better off using ‘new DomainClass(dto)’ or ‘bindData(new DomainClass(), dto)’.

    Hope that helps,

    Peter

  39. Danil

    Hi
    I have a grails project, structured this way:
    – “admin-domain-plugin” (plugin with only domains)
    – “admin-app” which embedds “admin-domain-plugin”

    i’m writing a module “A” (with it’s own domains), and i want it to communicate by jms with “admin-app” via DTO objects without knowing about admin domains.

    My first idea was to create “admin-dto-plugin”, include “admin-domain-plugin” in it, generate DTOs and than install “admin-dto-plugin” into module.
    The problem is with enums : no DTO objects are generated for them so enums are left in “admin-domain-plugin” and grails is unable to resolve them in module “A”.

    Is there any way to force grails to distribute some of sub-plugin’s classes along with plugin (to inherit them)? I don’t want to install “admin-domain-plugin” into module “A”

    Thanks in advance

  40. Srinivas

    Peter,

    Thank you very much for the response.

    I am currently using a constructor in Domain Class that takes DTO as input and assigns data to its variables.

    public def RewardAccount(RewardAccountDTO dto) {
    this.accountId = dto.getAccountId();
    this.cards = dto.getCards();
    this.customer = dto.getCustomer();
    this.nickName = dto.getNickName();
    this.transactions = dto.getTransactions();
    }

    Are you mentioning that the same can be achieved by writing:
    bindData(new RewardAccount(), RewardAccountDTO)
    If so, this can be done from services. right? And, where is the bindData() method available? Thanks for the info.

Leave a Reply

Your email address will not be published. Required fields are marked *