Page 1 of 4 123 ... LastLast
Results 1 to 10 of 31

Thread: Spring Roo with a services/DAO architecture

  1. #1
    Join Date
    Oct 2008
    Posts
    7

    Default Spring Roo with a services/DAO architecture

    I have been playing Spring Roo for a little while now, and when I'm not swearing at it because I can't remember the correct command (there appears to be some inconsistencies around the use of -class and -entity), I am pretty impressed.

    Anyway, the only thing holding me back from recommending we trial it at my company at the moment is the focus on domain driven design. Now I have no desire to get in to a religious debate around the pros and cons of domain driven vs services orientated; I believe they are both valid architectures, and each has its own benefits and draw backs. However where I work we have chosen to use a services orientated architecture as we believe it best suits the projects we work on.

    From a conversation I read on the Skyway blog between Ben and Jared, it sounds like Roo doesn't currently support a services orientated architecture. Now I know on one of your videos you showed using a services object within Spring Roo, however you had to write that object yourself.

    The ideal situation would be for the DAO and business logic objects to be created automatically by Roo, similar to the domain objects. I know in your presentation you said you couldn't possibly know all of the methods we may want to use, and that is correct. However you could create the basic crud methods, as well as any finders we choose to add.

    So to get to the real point of this post; If I wanted to create a Roo add-on that reused/extended the jpa add-on to create DAO and domain logic classes, where would I start? I would envision it as a choice when you installed JPA support (select either DDD or services), so you could use the same commands to create all of the fields for your entity.

    Any advice would be much appreciated.

    Thanks
    Andrew

  2. #2
    Join Date
    Mar 2008
    Location
    Sydney, AU
    Posts
    974

    Default

    Hi Andrew,

    At the moment Roo generated applications do not generate a traditional repository or service layer, but instead encourage a rich domain layer. The data access is fully included in the domain layer without actually showing up in the Java sources. It is, instead, handled by introduced code (ie Roo_Entity aspects). Since most JPA-managed repositories we see today do actually not add much value we believe Roo's approach can offer the same without the need for this extra layer. Keep in mind that Roo allows you to customize your data access as you wish.

    As for the services layer, it is really hard to figure out what you want to do in there. Roo allows you to create simple java classes to get you started. Roo cannot determine which methods for business logic that is not included in your rich domain layer you need in the services layer. Again, we don't much value in a services layer which acts as a simple facade that just hides a repository by mapping its methods 1:1. So long story short, Roo does not prevent you from creating your own services layer when needed but this cannot be generated by Roo as this layer would typically contain application specific business logic.

    HTH
    -Stefan

  3. #3
    Join Date
    Oct 2008
    Posts
    7

    Default

    Hi Stefan,

    I wasn't very consistent in my language. We typically use an architecture like this:
    * DAO layer - Contains the logic for writing to the data layer (typically data or web service). Named after the domain object.
    * business layer - Contains the business logic for performing operations on a domain object. Named after the domain object.
    * service layer - Handles transactions and actions that require calls to multiple business objects. These are named after the controller/s that use them, as the methods are based more around interface actions, rather than domain methods (our way of avoiding service layers that are merely pass throughs).


    My hope with service based JPA addon would be that instead of generating the JPA methods in the domain object, it would create the domain object as a POJO, and put all of the logic in a DAO object with the regular CRUD methods. I figured it could be done by copying the current JPA addon and making some adjustments, although maybe I have underestimated the complexity.

    I understand what you are saying about the extra layers not adding any value. It is true, in many causes the methods simply pass through to the DAO layer. However I tend to work with complicated applications that involve multiple databases as well as web services. For that sort of interaction I feel the extra layers help separate the complexity, although it could be that I don't fully understand how that application should be structured using DDD. As they say, it is hard to teach an old dog new tricks

    I will continue to play with Roo to see if we can use it for any upcoming projects. You never know, maybe you will convert me to a DDD way of thinking.

    Thanks
    Andrew

  4. #4
    Join Date
    Mar 2009
    Posts
    19

    Default

    bazza80, if you want a DAO layer, why not just replace the EntityManager in your Entities with a dedicated DAO object? This way you can have your DAO layer that fits perfectly into the Roo-generated rich domain model. Each entity will simply delegate data access operations to the DAO abstraction, which can be modified to use any available data access strategy (JPA, JDBC, IBATIS, ...).

    Cheers,
    Jukka

  5. #5
    Join Date
    Aug 2004
    Location
    Sydney, Australia
    Posts
    2,768

    Default

    I'd argue that JPA is the modern abstraction over persistence for enterprise Java apps, so plugging in a different DAO implementation isn't really something that is done that often. If people want to persist via some other technology, they need only provide an EntityManager implementation and have Spring dependency inject it whenever @PersistenceContext is declared on a field.

    One strong argument in support for a separate DAO layer is the ease it can be mocked during testing. However, Roo already supports mocking of the persistence layer via Rod Johnson's work in ROO-92:

    http://jira.springframework.org/browse/ROO-92

    Another argument in support of a dedicated DAO layer is the separation of concerns it provides. Certainly if a developer needs to manage most or all of the code within their project it is helpful to focus on one group of technical challenges at a time, and separate these into clear layers. However, in a Roo project the Roo system takes care of these challenges and cleanly separates the persistence code into its own compilation unit that the programmer need never deal with (unless they especially wish to). So separation of concern arguments are valid, but the fact a developer need not deal with the persistence concern themselves and the fact that Roo does use separation of concern at implementation time relieves the need of having a formal DAO layer for this reason.

    A real danger with code generation is to generate lots and lots of code (given it's so easy to do so). It would be absolutely trivial for us to generate a DAO layer, but given how trivial it would be I am really conservative about going down that path until I see some compelling and rigorous engineering arguments that show why we need a DAO layer. The problem with having a DAO layer is we have so many more types in the system (an interface and implementation at minimum, likely for every single entity), plus the more complicated IoC wiring that would necessitate (you can't just use the entity's methods anymore, but you need to now have fields in your classes that wish to use the DAOs and have these dependency injected). This level of complexity is too much like "old school Java" with its associated poor productivity. The typical arguments about swapping to alternate implementations, facilitating mock testing and separation of concern are addressed via the Roo approach without requiring a DAO layer.

    I'd also note that other modern frameworks like Rails have not found the incorporation of persistence methods into the entities (as Roo does) a problem. Indeed I'd argue the Roo approach is even more sound as it's backed by a pluggable, high performance JPA implementation and not simply the active record pattern. If having persistence methods in entities was really a major problem, a lot of Rails projects seem to be working perfectly successfully regardless.
    Ben Alex
    Project Founder, Spring UAA, Spring Roo and Spring Security

  6. #6
    Join Date
    Mar 2009
    Posts
    19

    Default

    Quote Originally Posted by Ben Alex View Post
    If having persistence methods in entities was really a major problem, a lot of Rails projects seem to be working perfectly successfully regardless.
    I personally don't see any problem in having persistence methods in an Entity, simply because we're not doing much there but delegating to the EntityManager. So concerns are separated for the most part.

    In a related vein, in case one/Roo creates an abstract base entity that sports the id and version fields, would it be appropriate to put a (protected) entityManager field and the generic persist(), update() and remove methods there as well? Something along the lines of:

    Code:
    @Configurable
    @MappedSuperclass
    public abstract class PersistentObject {
        
        @Transient
        @PersistenceContext
        protected EntityManager entityManager;
        
        @Id
        @Column(name = "id")
        @GeneratedValue(strategy = GenerationType.AUTO)
        private Long id;
    
        @Version
        @Column(name = "version")
        private Integer version;
        
        public final Long getId() {
            return this.id;
        }
    
        public final void setId(Long id) {
            this.id = id;
        }
    
        public final Integer getVersion() {
            return this.version;
        }
    
        public final void setVersion(Integer version) {
            this.version = version;
        }
        
        @Transactional
        public void persist() {
            this.entityManager.persist(this);
        }
    
        @Transactional
        public void remove() {
            PersistentObject object;
            if (this.entityManager.contains(this)) {
                object = this;
            } else {
                object = this.entityManager.find(getClass(), this.id);
            }
            this.entityManager.remove(object);
        }
    
        @Transactional
        public void update() {
            PersistentObject merged = this.entityManager.merge(this);
            this.entityManager.flush();
            this.id = merged.getId();
        }
        
        public static EntityManager entityManager() {
            return new EntityManagerHolder().entityManager;
        }
        
        private static class EntityManagerHolder extends PersistentObject {     
        }
    }
    Cheers,
    Jukka

  7. #7
    Join Date
    Sep 2009
    Posts
    21

    Default

    Andrew,

    I am pretty sure you have read Stefan's reply, but I would like to highlight the following again -

    >At the moment Roo generated applications do not generate a traditional repository or service layer, but instead encourage a rich domain layer

    My interpretation of this is, this is the reason why persist etc methods are generated inside the domain objects and Roo does not generate any DAO.

    Hope this helps to clarify things a bit.

  8. #8
    Join Date
    Dec 2005
    Location
    Estonia
    Posts
    11

    Default Design scalability concerns

    I don't have much experience with Spring Roo but as Ben also said many modern frameworks (e.g Grails) are using this approach where entities can have access to some simple persistence API.

    I have been using Grails for some time now which AFAIK uses quite similar approach as Spring Roo. In general it results in more domain centric design which is good. However I still have some concerns which are mostly related to scalability of this kind of design.

    1) it is not possible to separate pure domain logic and persistence logic
    Domain entities themselves are now in charge of persisting themselves - calling some save() method.
    2) what happens if we need more complex queries?
    Now we will expose not just simple API but already some query language to our domain entity (I don't know how this is handled in Spring Roo but probably this applies for it also)
    3) what happens if we need to encrypt some data before saving to database?
    one solution is to use separate transient and persistent fields but even then entity would most likely need to depend on some encryption API

    The result of above issues is that domain entities are now bigger hence harder to maintain

    Does anyone have any good solution to these issues? We could of course re-introduce Repository/DAO layer but that seems to contradict with the idea of the framework.


    ---
    Ürgo Ringo
    Head of R&D
    Aqris Software
    Last edited by urgo; Oct 3rd, 2009 at 08:41 AM.

  9. #9
    Join Date
    Aug 2004
    Location
    Sydney, Australia
    Posts
    2,768

    Default

    1) it is not possible to separate pure domain logic and persistence logic. Domain entities themselves are now in charge of persisting themselves - calling some save() method.
    Because JPA is so heavily used in current enterprise Java apps, and it provides a persistence layer abstraction via the EntityManager interface, it is possible to provide an alternate implementation if required.

    Virtually no Roo-generated code calls any persistence method introduced into entities, with the notable exception being scaffolded controllers and automated integration tests. As such there is no need for domain objects to themselves call their own persist methods.

    Most often someone will write a @Transactional services layer method that does something meaningful with the domain object and then calls the persist() method. Naturally if the entity was acquired in the same unit of work it will be attached to the session and therefore it isn't even required to call persist() explicitly. This automatic JPA behavior underscores the diminishing role of persistence-related methods anyway, particularly when coupled with lazily loaded associations. As such relying on special DAO/repository layer implementations to orchestrate specific update or fetch semantics is generally impractical in this era of JPA, so you're better off at looking at JPA implementation features to hook such logic in (eg event listeners in JPA).

    2) what happens if we need more complex queries? Now we will expose not just simple API but already some query language to our domain entity (I don't know how this is handled in Spring Roo but probably this applies for it also)
    Given Roo introduces members to Java types via AspectJ inter-type declarations, there is already separation of concern. Only the compiled class file contains both persistence methods and non-persistence methods. Roo automates the creation of finders from the zero or more finder name expressed in the @Roo annotation on the entity. As such the user doesn't need to do anything more than indicate what finder method they'd like created.

    Certainly it is true that more complex finder queries cannot be handled by Roo and the user will still need to write those. In this regard the user will need to know JPA QL or an equivalent approach, but nothing stops the user from using ITDs in the same way as Roo does to achieve compilation unit separation. For example, the user could write a PersonFinders.aj class which introduces their very complicated finders in Person.class at compile time. That way Person.java still looks and feels like a proper entity at a source code level, but from a programming convenience level the finder is available to other layers.

    3) what happens if we need to encrypt some data before saving to database? One solution is to use separate transient and persistent fields but even then entity would most likely need to depend on some encryption API
    You have a number of choices here. You could look at JPA event listeners as touched on above, or alternately you could employ some clever AspectJ field get/set advice. The advice could perform actual encryption/decryption. Alternately you could tackle encryption/decryption in the layers closer to the user, as that way your business logic in the services layer need not content with potentially-encrypted values. Of course some databases provide encryption themselves, and then you have encrypted file systems as well. These latter layers are likely to provide better encryption performance and not adversely impact your ability to perform SQL queries (as the queries can be expressed in an unencrypted form). It really depends on the business goals of encryption/decryption in the first place, but I am confident the requirement can be satisfied despite having persistence members introduced to the entity.
    Ben Alex
    Project Founder, Spring UAA, Spring Roo and Spring Security

  10. #10
    Join Date
    Dec 2005
    Location
    Estonia
    Posts
    11

    Default

    Ben, thank you for your thorough reply.

    Does Spring Roo team have some general recommendation whether persistence calls should be kept out of domain objects or not?

    Making persistence layer calls available through static methods of entities seems to advocate direct access to persistence API from domain layer. This is interesting because there has been quite heated discussion about this topic in DDD yahoo forum and some people like Eric Evans do not seem to recommend such practice in general.


    ---
    Ürgo Ringo
    Head of R&D
    Aqris Software

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •