-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 11 posts ] 
Author Message
 Post subject: Assemblers
PostPosted: Thu Aug 12, 2004 12:25 pm 
Regular
Regular

Joined: Tue Dec 09, 2003 2:39 pm
Posts: 106
Location: Toronto, Canada
Background

We're making use of the Assembler pattern in a truly distributed architecture that requires the passing of DTOs to rich (Swing/SWT) clients.

What we'd like to have is a generic assembly method for each domain/entity to DTO and are considering implementing them on a use-case by use-case basis instead.

The reason is because we don't want to introduce a Hibernate dependency check for LazyInitializationExceptions inside the assemblers whenever a proxy or uninitialized collection is encountered because a particular use-case doesn't require it, and quiver at the thought of adding flags and structured logic indicating whether a field is or isn't to be loaded inside the entity and assemblers respectively.

Question

How are others in the community are dealing with these issue? Is the use-case by use-case assembler the only route since we cannot make use of filters/interceptors, etc. We don't want to move the assembler call inside the transaction because this will result in a different kind of N+1 select problem: initialization of unwanted members because they are unknowingly being loaded because the generic assembler is invoking the uninitialized associations as a result of trying to stuff them into DTOs.

Please note that we're currently using Session EJBs as the implementing business interface responsible for transaction demarcation using the ThreadLocalSession pattern, CMT and nested transactions inside DAOs. We are not employing Spring as a framework.

Hibernate version: 2.1.4

Code between sessionFactory.openSession() and session.close():

Keep in mind we're using Session Beans.

We'd like this type of generic assembly usage:

Code:
...
       Session session = AcmeThreadLocalSession.currentSession();
       List entityList = null;
       
       try {
          entityList = AcmeDAOFactory.getDAOFactory().getEntiyDAO().findAll();
          session.flush();
       }
      catch (Exception e) {
         getSessionContext().setRollbackOnly();
         throw (AcmeException) AcmeExceptionConverter.convert(e);
      }
       finally {
           AcmeThreadLocalSession.closeSession();
       }
       
        /* here's where we swizzle the entity into a DTO.  If we reuse this     
        method in another use-case which may produce a deeper or
        shallower entity graph in the list, this will result in a   
        LazyInitializationException.*/

       return EntityAssembler.writeDTO(entityList);
...


Regards,
Roll


Top
 Profile  
 
 Post subject: Way off base?
PostPosted: Mon Aug 16, 2004 9:56 am 
Regular
Regular

Joined: Tue Dec 09, 2003 2:39 pm
Posts: 106
Location: Toronto, Canada
Any suggestions?

If we write assembly methods on a use-case by use-case basis, then we can move the assembly invocation back into the transaction. However, I don't know if this lazy-initialization-indirection is considered good design.

(Also, just for clarity, I was referring to generic domain object assemblers, where each domain would have its own assembler object. Not one generic assembler that assembles all domain objects into DTOs).

Regards,
Roll


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 16, 2004 2:53 pm 
Regular
Regular

Joined: Tue Dec 09, 2003 2:39 pm
Posts: 106
Location: Toronto, Canada
We are considering using generic assembler methods that also take an object in the signature that simply identifies what associations have been initialized so the assembler knows what to provide to the DTO.

For example:

[code]
public class SomeEntityAssembler {
...
public static SomeEntityDTO writeDTO(SomeEntity entity, SomeEntityLazyFlags flags) {
SomeEntityDTO dto = new SomeEntityDTO();
if(flags.isTitleInitialized()) {
dto.setTitle(case.getTitle());
}


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 16, 2004 5:50 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
1. Having an LazyInitializationException, but beeing able to use the dettach object support and write n classes
2. Using DTO and DTO factories and having 2n or even 3n classes

I made my choice.

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 17, 2004 9:26 am 
Regular
Regular

Joined: Tue Dec 09, 2003 2:39 pm
Posts: 106
Location: Toronto, Canada
emmanuel wrote:
2. Using DTO and DTO factories and having 2n or even 3n classes I made my choice.


Thanks, Emmanuel. Could you please elaborate? Are you referring to 2n or 3n DTO factories/Assemblers for each use-case?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 18, 2004 3:20 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
(1 persistent class + 1 DTO) * n entities in the domain model.
(1 persistent class + 1 DTO + 1 DTO factory) * n entities in the domain model.

I don't like that redundency

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 18, 2004 2:37 pm 
Regular
Regular

Joined: Tue Dec 09, 2003 2:39 pm
Posts: 106
Location: Toronto, Canada
Quote:
(1 persistent class + 1 DTO + 1 DTO factory) * n entities in the domain model.


I don't like the redundancy either. However, in the scenario above, how would you accomodate for different DTO graph loading levels? Would each DTO factory have multiple assembly methods per each use-case? Or possibly you'd pass in some loading level object (like I do in one of my examples above) that would indicate what associations to load? I see the latter getting pretty hairy with deeply nested associations that need to be loaded.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Aug 19, 2004 3:44 am 
Regular
Regular

Joined: Wed Aug 18, 2004 5:16 am
Posts: 69
Location: Modena, Italy
My problem is very similar.

I think that will be a nice feature to optionally "clean" object when they become detached.
Clean means remove from the object graph all the Hibernate classes (for collections) and proxys using only java collection and the persistent classes, so we can obtain a object graph usable by all remote clients directly without managing DTOs.

What do you think about this? Is possible?


Top
 Profile  
 
 Post subject:
PostPosted: Thu Aug 19, 2004 9:14 am 
Regular
Regular

Joined: Tue Dec 09, 2003 2:39 pm
Posts: 106
Location: Toronto, Canada
It'd be cool, but the Hibernate fellas would have to answer that one.

Having slept on this one I think I will attempt to approach my assembly conundrum this way:
    1. Have all assemblers assume that what is in the entity graph is what is intended in the DTO graph
    2. Add an isInitialized method to my DAOUtil interface
    3. Have my HibernateUtil implement this to check whether an association was initialized.
    4. Have the assembler call the above method prior to swizzling the association into the DTO


Proceeding with the above will allow my assemblers to be DAO agnostic -- I know, I know, too much hype over DAO coupling <sigh>. I have my opinions, but this is a real requirement that I have to respect.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 23, 2004 1:39 pm 
Regular
Regular

Joined: Tue Dec 09, 2003 2:39 pm
Posts: 106
Location: Toronto, Canada
On further thought :)

By keeping the assembler methods inside the transaction and having use-case specific assembly methods we can rid ourselves of polluting our DAO layer with the additional overhead of building dynamic queries (for generalized DAO access with loading level flags)/or use-case specific DAO methods.

Lazy virtual proxies/ghosts isn't something unique to Hibernate and certainly it would be a much cleaner OO to allow the assembler use case methods to simply access the association they need for the DTO they are building.

I've made my choice now too.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 30, 2004 12:50 am 
Regular
Regular

Joined: Tue Sep 30, 2003 11:27 am
Posts: 60
Location: Columbus, OH, USA
rollatwork wrote:
On further thought :)

By keeping the assembler methods inside the transaction and having use-case specific assembly methods we can rid ourselves of polluting our DAO layer with the additional overhead of building dynamic queries (for generalized DAO access with loading level flags)/or use-case specific DAO methods.

Lazy virtual proxies/ghosts isn't something unique to Hibernate and certainly it would be a much cleaner OO to allow the assembler use case methods to simply access the association they need for the DTO they are building.

I've made my choice now too.


Yea, I like that approach as well. You might be able to use commons-beanutils to make property copying a bit easier too. Thanks for posting your solution.
Scott


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 11 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.