Basic understanding of DAO pattern

I'm starting to think (based on my confusion trying to implement the DAO pattern and some responses to another forum topic I posted) that I don't fully understand the DAO pattern. (This doesn't really surprise me).

If I have a data model class, for example Shape, would I...

A. write a DAO class to help create, retrieve, update, and delete Shape instances and work with those instances directly?

or

B. write a DAO class as a wrapper (encapsulating the actual data access code) around a Shape object so that none of my code ever references Shape objects directly?

I used to think that approach (B) was the point of the DAO pattern, but after looking to the Hibernate Caveat Emptor sample program, I'm starting to think approach (A) is more correct.

Any DAO design experts out there that wouldn't mind helping out an experienced Java developer with very little data layer experience?

A couple of side questions:

1. When using the DAO pattern, does presentation layer code (in my case Swing widgets) know that the data model objects being rendered repesent various data store objects and therefore the renderers must use the DAOs to get information about the data model objects? Or rather, does the DAO pattern make the data access completely transparent to the rendering code?

2. Similar to question 1: Should I expect to see code like shapeDAO.saveShape(myShape) in my presentation layer code (in event listeners)? Or should it look more like shapeDAO.save()?

3. If I have a widget that renders a bunch of shapes, would that widget's model contain a bunch of Shape instances or rather a bunch of ShapeDAO instances?

I realize that I have asked a lot of questions here. Any help is greatly appreciated.

[1794 byte] By [jds@ku.edua] at [2007-10-3 1:21:22]
# 1

> If I have a data model class, for example Shape,

> would I...

> A. write a DAO class to help create, retrieve,

> update, and delete Shape instances and work with

> those instances directly?

> or

I think this is what Hibernate/JDO would have you believe. Its so clean and pretty looking that its almost always the advertised way. But complexity often makes this not the best way. For instance, with this implementation, Shape would have methods such as

#getExtents

#boolean hitTest(Point)

both of these are sort of 'business method' (data model?). But as a result of Shape directly being the ORM class you may have methods such as

#getXYZ

Where XYZ requires some special hibernate quering or sorts. So you end up with business logic and query logic in the same class! Which I do not like. Again, if its simple like a Shape, then likely you wont have any query logic and this technique becomes pretty and straightforward.

> B. write a DAO class as a wrapper (encapsulating the

> actual data access code) around a Shape object so

> that none of my code ever references Shape objects

> directly?

>

I think this is closer to my preferred way but I still don't think this is proper DAO because you are using the DAO as if it is business layer. i.e. you will implement the 'shape' interface on the DAO which to me is not right.

> I used to think that approach (B) was the point of

> the DAO pattern, but after looking to the Hibernate

> Caveat Emptor sample program, I'm starting to think

> approach (A) is more correct.

>

> Any DAO design experts out there that wouldn't mind

> helping out an experienced Java developer with very

> little data layer experience?

>

Not expert just experienced.

> A couple of side questions:

> 1. When using the DAO pattern, does presentation

> layer code (in my case Swing widgets) know that the

> data model objects being rendered repesent various

> data store objects and therefore the renderers must

> use the DAOs to get information about the data model

> objects? Or rather, does the DAO pattern make the

> data access completely transparent to the rendering

> code?

>

No. You are making your DAOs as your 'business model' again.

> 2. Similar to question 1: Should I expect to see code

> like shapeDAO.saveShape(myShape) in my presentation

> layer code (in event listeners)? Or should it look

> more like shapeDAO.save()?

>

Same mistake.

> 3. If I have a widget that renders a bunch of shapes,

> would that widget's model contain a bunch of Shape

> instances or rather a bunch of ShapeDAO instances?

>

Same mistake.

> I realize that I have asked a lot of questions here.

> Any help is greatly appreciated.

Again, Im no expert and there are two ways to do this I know of. But both do not involve the mistake you made above. I think your mistake is that you are missing a layer.

You have what I think you are calling a 'data model' layer. Which is all the methods your presentation layer will use like

#getSize()

#getLocation()

etc..

You have your DAO layer which will probably also have

#getWidth()

#getHeight()

#getX()

#getY()

The DAO layer is considered by some to be equivalent to the persistence layer. I have essentially agreed with this. So the DAO classes return the valueObjects which are used by the data model layer.

Here is non-valueObject using example

//data layer/business layer

interface Shape {

Point getLocation();

Dimension getSize() throws DataException;

}

interface ShapeDAO{

int getX();

int getY();

int getWidth() throws DAOException ;

int getHeight() throws DAOException;

}

class ShapeDataModel implements Shape

ShapeDAO shapeDao;//how you get the DAO into this class is another issue.

public Point getLocation(){

int x = shapeDao.getX();

int y = shapeDao.getY();

return new Point(x,y);

}

public Dimension getSize() throws DataException{

try {

int w = shapeDao.getWidth();

int h = shapeDao.getHeight();

return new Dimension(w,h);

}

catch(DAOException e){

throw new DataException(e);

}

}

}

//DAO implementation

class MainShapeDAO implements ShapeDAO {

//your JDO/hibernate/JDBC guts to here with such methods as

static ShapeDAO getShapeDao(identifier){

return new MainShapeDAO(identifier);

}

public int getX() {

return x;

}

public int getY(){

return y;

}

public int getWidth() throws DAOException{

try {

int width = queryWidth();

return width;

}

catch(//SQL/JDO/HibernateException...){

throws DAOException(e);

}

}

public int getHeight() throws DAOException{

try {

int height = queryHeight();

return height;

}

catch(//SQL/JDO/HibernateException...){

throws DAOException(e);

}

}

}

A value object using DAO would be different in that it would have methods on the DAO such as

#store(valueobject)

and all the get/set methods would be on the value object and not the DAO interface. Then the DAO interface would be mostly concerned with returning the value objects.

also the value object way would allow you to return an essentially plain object to tinker around with for a while. You would then save it when you felt the need. You may put a save method on your data model layer so the user can decide this, or you may save based on other factors you calculate in the business layer and not ask the user at all. I think its entirely fair that the business layer decides when to save.

_dnoyeBa at 2007-7-14 18:18:35 > top of Java-index,Other Topics,Patterns & OO Design...
# 2

> Again, Im no expert and there are two ways to do this

> I know of. But both do not involve the mistake you

> made above. I think your mistake is that you are

> missing a layer.

>

> You have what I think you are calling a 'data model'

> layer. Which is all the methods your presentation

> layer will use like

> #getSize()

> #getLocation()

> etc..

>

> You have your DAO layer which will probably also

> have

> #getWidth()

> #getHeight()

> #getX()

> #getY()

Too granular. This will be one chatty DAO.

This design suggests that if I have shapes table in my database, with a primary key shapeId, width, height, x, and y, and I have a Shape model object with those same attributes, then if I wanted to get a Shape out of the database I'd have to do four queries, one for each attribute.

Four network roundtrips for a single object. Do I understand this correctly?

> The DAO layer is considered by some to be equivalent

> to the persistence layer. I have essentially agreed

> with this. So the DAO classes return the

> valueObjects which are used by the data model layer.

>

> Here is non-valueObject using example

>

> //data layer/business layer

> > interface Shape {

>Point getLocation();

> Dimension getSize() throws DataException;

> }

> interface ShapeDAO{

>int getX();

> int getY();

>int getWidth() throws DAOException ;

> int getHeight() throws DAOException;

> }

> class ShapeDataModel implements Shape

> ShapeDAO shapeDao;//how you get the DAO into this

> class is another issue.

Dependency injection is a good way to do it.

>public Point getLocation(){

>int x = shapeDao.getX();

>int y = shapeDao.getY();

>return new Point(x,y);

This design is inherently inefficient.

Here's my take on it:

[code]

package model;

public class Shape implements Serializable

{

private Long shapeId;

private int x;

private int y;

private int width;

private int height;

// constructors, getters & setters; equals & hashCode omitted for brevity

}

package persistence;

public interface ShapeDao

{

Shape findById(Long id);

List<Shape> findAll();

void saveOrUpdate(Shape s);

void delete(Shape s);

void delete(long id);

}

Implement the ShapeDao in the technology of your choice (JDBC, JDO, Hibernate, iBatis, JPA, etc.)

If I want a Shape, I query by primary key and do one network roundtrip, not four. If I turn on caching, and my persistence technology takes advantage of it, I might do zero network roundtrips if I have a cache hit on that query.

%

duffymoa at 2007-7-14 18:18:35 > top of Java-index,Other Topics,Patterns & OO Design...
# 3
Also, there's no way in that shape DAO to identify any attibute with a particular primary key. How does that work?%
duffymoa at 2007-7-14 18:18:35 > top of Java-index,Other Topics,Patterns & OO Design...
# 4

> A couple of side questions:

> 1. When using the DAO pattern, does presentation

> layer code (in my case Swing widgets) know that the

> data model objects being rendered repesent various

> data store objects and therefore the renderers must

> use the DAOs to get information about the data model

> objects? Or rather, does the DAO pattern make the

> data access completely transparent to the rendering

> code?

I think the Listeners for Swing widgets are part of the Controller in this case. If you have the Controllers contact a well-defined service layer you can hide the persistence completely behind the service interface. The service implementation uses domain objects and the persistence layer to accomplish a task on the Controllers behalf. If you decide to go with another UI (e.g., a web-based UI), it can use the same services.

> 2. Similar to question 1: Should I expect to see code

> like shapeDAO.saveShape(myShape) in my presentation

> layer code (in event listeners)? Or should it look

> more like shapeDAO.save()?

Neither. Have the listeners contact a service layer to do what's needed and let it handle persistence.

> 3. If I have a widget that renders a bunch of shapes,

> would that widget's model contain a bunch of Shape

> instances or rather a bunch of ShapeDAO instances?

Not DAOs. At that point they should have the data that needs to be passed to a renderer (e.g. a List<Shape> or whatever you're going to draw). The renderer does not care where the data came from or whether it persists. All it needs is data to draw.

%

duffymoa at 2007-7-14 18:18:35 > top of Java-index,Other Topics,Patterns & OO Design...
# 5

Im not sure what the "service layer" is/does. Can you elaborate on this a bit?

Also, as far as the layers go, let me see if I have this all straight in my head...

1. Presentation Layer (Swing code, ShapeViewer class)

2. Data model (the 'model' package as you described, Shape class, Set<Shape>, etc)

3. Service layer (?)

4. Persistence layer (Hibernate, DAOs, ShapeDAO class, etc)

Does this look right to you, duffymo (or others)?

P.S. I REALLY appreciate all of the replies. This is slowly starting to come together in my head. I'm really starting to believe that I inherited a project that was missing a layer (service layer) and had DAO-type code scattered everywhere that we needed to get an object from the DB. (Yeah, Hibernate was keeping us out of SQL, but we still had session management code everywhere we looked)

jds@ku.edua at 2007-7-14 18:18:35 > top of Java-index,Other Topics,Patterns & OO Design...
# 6

It was not my objective to create an efficient implementation. Simply to show how the layers interact and how the DAO pattern can be used. The granularity is your choice. For me, I can update 1 value very much more frequently than the other values so its been optimized for my usage pattern.

Again, where I have said ValueObject, I should have said TransferObject.

Dependency injection is how you can get the main DAO into the 'business models' which I use interchangeably with the term 'data models.' This does not detail how you get a specific DAO into a specific data model.

Also when you do this I am still confused;

public interface ShapeDao

{

Shape findById(Long id);

List<Shape> findAll();

void saveOrUpdate(Shape s);

void delete(Shape s);

void delete(long id);

}

Here, is "Shape" your business model, or a transfer object? Looks like a TransferObject.

_dnoyeBa at 2007-7-14 18:18:35 > top of Java-index,Other Topics,Patterns & OO Design...
# 7

> It was not my objective to create an efficient

> implementation. Simply to show how the layers

> interact and how the DAO pattern can be used. The

> granularity is your choice. For me, I can update 1

> value very much more frequently than the other values

> so its been optimized for my usage pattern.

I guess we'll leave it to the OP to decide which is more helpful.

>

> Again, where I have said ValueObject, I should have

> said TransferObject.

What's the diffrence in your opinion? I've stated my definition of Value Object (credit to Eric Evans for that). Transfer Object usually makes me think of a Value Object that's for the purpose of ferrying data between two layers. It's a Core J2EE Pattern that came about because people found out that passing entity EJBs around was a terrible idea. I think it's going to be thought of as more of an anti-pattern as time goes on.

> Dependency injection is how you can get the main DAO

> into the 'business models' which I use

> interchangeably with the term 'data models.' This

> does not detail how you get a specific DAO into a

> specific data model.

It's one way to do it.

> Also when you do this I am still confused;

> > public interface ShapeDao

> {

>Shape findById(Long id);

> List<Shape> findAll();

>

>void saveOrUpdate(Shape s);

> void delete(Shape s);

>void delete(long id);

>

>

> Here, is "Shape" your business model, or a transfer

> object? Looks like a TransferObject.

Nope, it's a domain object, not a transfer object.

%

duffymoa at 2007-7-14 18:18:35 > top of Java-index,Other Topics,Patterns & OO Design...
# 8
Just in case it's not clear, I'm not a transfer object fan.%
duffymoa at 2007-7-14 18:18:35 > top of Java-index,Other Topics,Patterns & OO Design...
# 9

> I guess we'll leave it to the OP to decide which is

> more helpful.

>

It should be helpful to show how DAO layer interacts with domain objects, etc. It was not my intention to recommend a level of granularity when I don't even know the requirements of the OPs system or classes. Its an example implementation, but objective is only to show the interaction of layers...

> >

> > Again, where I have said ValueObject, I should

> have

> > said TransferObject.

>

> What's the diffrence in your opinion? I've stated my

> definition of Value Object (credit to Eric Evans for

> that). Transfer Object usually makes me think of a

> Value Object that's for the purpose of ferrying data

> between two layers. It's a Core J2EE Pattern that

> came about because people found out that passing

> entity EJBs around was a terrible idea. I think it's

> going to be thought of as more of an anti-pattern as

> time goes on.

>

I only brought it up to help me understand what you are doing. I dont have domain or transfer objects returned by my DAOs.

> > Also when you do this I am still confused;

> > > > public interface ShapeDao

> > {

> >Shape findById(Long id);

> > List<Shape> findAll();

> >

> >void saveOrUpdate(Shape s);

> > void delete(Shape s);

> >void delete(long id);

> >

> >

> > Here, is "Shape" your business model, or a

> transfer

> > object? Looks like a TransferObject.

>

> Nope, it's a domain object, not a transfer object.

>

> %

1. The domain objects should know about the DAO interface.

2. The DAO interfaces are owned by the domain layer.

The DAO interfaces can not contain references to domain objects without forcing the DAO implementaiton to be aware of domain objects.

If you make your DAO interface return domain objects, then your presentation layer must now know about both the DAO objects AND the domain objects since the DAO object is not the way to get at the domain object implementation. This is a lot of layer mixing.

My presentation layer is aware only of the interfaces to the domain objects.

My domain layer is aware only of the interfaces to the DAO objects, and implements the interfaces to the domain objects.

My DAO layer implements the interfaces to the DAOs.

The interfaces to the domain objects are kept in a different package that can be freely used by the presentation layer.

_dnoyeBa at 2007-7-14 18:18:35 > top of Java-index,Other Topics,Patterns & OO Design...
# 10

> It should be helpful to show how DAO layer interacts

> with domain objects, etc. It was not my intention to

> recommend a level of granularity when I don't even

> know the requirements of the OPs system or classes.

> Its an example implementation, but objective is only

> to show the interaction of layers...

I think it's pretty easy to say that a chatty model won't scale well.

> I only brought it up to help me understand what you

> are doing. I dont have domain or transfer objects

> returned by my DAOs.

Really? Then what are they getting out of persistent store?

"DAO layer interacts with domain objects" - sounds like you're returning domain objects when you write this. I think that's what the DAO is supposed to do. There's no other reason for it to exist.

> 1. The domain objects should know about the DAO interface.

No, mine don't. It's the other way around - the DAO knows about the objects it's creating, but the objects don't have to know that they're persisted.

> 2. The DAO interfaces are owned by the domain layer.

Maybe not.

> The DAO interfaces can not contain references to

> domain objects without forcing the DAO implementaiton

> to be aware of domain objects.

I think this is incorrect. That's the whole reason for DAOs to exist: to manage the interaction between domain objects and the persistent store. The persistence layer knows all about the domain layer, but not the other way around.

The service layer knows about both the domain and persistence layers, because that's where use cases and units of work are accomplished.

> If you make your DAO interface return domain objects,

> then your presentation layer must now know about both

> the DAO objects AND the domain objects since the DAO

> object is not the way to get at the domain object

> implementation. This is a lot of layer mixing.

No, the presentation layer does not know anything about DAOs. It talks to a service layer that hide how the use cases are implemented. The presentation layer knows that it needs to call a particular service to satisfy a request; it knows what the contract is with the service layer ("pass me this and I'll provide you that"), and it renders what it gets back from the service layer. No knowledge of DAOs or how that response was generated.

I don't mind passing domain objects to the persistence layer. I don't think there's blanket harm in doing so.

So tell me - what are the DAOs returning of not domain objects?

> My presentation layer is aware only of the interfaces

> to the domain objects.

So if you have a Person object you've got a Person interface in front of it? What's that buying you? Interfaces are supposed to hide implementation and allow you to change if necessary without affecting clients. I don't think interfaces for domain objects like Person or Address are a good use of the idiom.

> My domain layer is aware only of the interfaces to

> the DAO objects, and implements the interfaces to the

> domain objects.

No, I think it's the other way around - the persistence layer knows about the domain it's persisting, but not the other way around.

The only way I would agree would be if you insisted that domain objects should handle their own persistence. In that case they'd have a DAO as a private data member and would implement a CRUD interface. If they wanted to be saved they'd pass themselves to the save method ("put me away in the database please, Mr. DAO"). In that case the domain object has to know about the persistence layer, and the coupling runs in both directions.

I'd say that my way means a one-way coupling from persistence to domain.

> My DAO layer implements the interfaces to the DAOs.

>

> The interfaces to the domain objects are kept in a

> different package that can be freely used by the

> presentation layer.

I disagree with your concept of layers.

%

duffymoa at 2007-7-14 18:18:35 > top of Java-index,Other Topics,Patterns & OO Design...
# 11

> I think the Listeners for Swing widgets are part of

> the Controller in this case. If you have the

> Controllers contact a well-defined service layer you

> can hide the persistence completely behind the

> service interface. The service implementation uses

> domain objects and the persistence layer to

> accomplish a task on the Controllers behalf. If you

> decide to go with another UI (e.g., a web-based UI),

> it can use the same services.

>

> > 2. Similar to question 1: Should I expect to see

> code

> > like shapeDAO.saveShape(myShape) in my

> presentation

> > layer code (in event listeners)? Or should it

> look

> > more like shapeDAO.save()?

>

> Neither. Have the listeners contact a service layer

> to do what's needed and let it handle persistence.

duffymo, I'm still not sure what a "service layer" should provide. I would really like to have some more info about that. I think you're onto something here. We plan on adding a really simple, web-based UI to this in the future. I would love to design it now so that addition is easy to accomplish.

jds@ku.edua at 2007-7-14 18:18:35 > top of Java-index,Other Topics,Patterns & OO Design...
# 12

> No, I think it's the other way around - the

> persistence layer knows about the domain it's

> persisting, but not the other way around.

>

> The only way I would agree would be if you insisted

> that domain objects should handle their own

> persistence. In that case they'd have a DAO as a

> private data member and would implement a CRUD

> interface. If they wanted to be saved they'd pass

> themselves to the save method ("put me away in the

> database please, Mr. DAO"). In that case the domain

> object has to know about the persistence layer, and

> the coupling runs in both directions.

>

This is what I do. But as I indicated the DAO interface is owned by the data model. Therefore, the datamodel is not aware of or dependent upon the actual DAO implementation.

> I'd say that my way means a one-way coupling from

> persistence to domain.

>

I too have one way coupling from persistence to domain. My DAOs are dependent upon the interfaces provided by the domain.

My domain objects have certain lifecycle/cacheing requirements that I would prefer not to implement on the DAO. The DAO should be about managing persistence, not lifecycle of domain objects. This is why I could not have the domain objects coming out of the DAOs.

Its worth consideration though. I currently have a sort of pseudo layer in that my domain objects all have static methods on them which are there to manage their lifecycle and cacheing. I did read before that sometimes static methods is an indication of the need for another object. If I can change a bit and dump these static method it wouldn't be bad.

Message was edited by:

_dnoyeB

After thinking about this over lunch I have a question. Your presentation layer uses the methods on the domain object to present the data. Your DAO layer uses the methods on the domain object to store the data. Are you using the same methods for both? Or do you have some methods that presentation can't see that persistence uses? Such as a persistence interface on your domain objects? Or are you using reflection or what?

_dnoyeBa at 2007-7-14 18:18:35 > top of Java-index,Other Topics,Patterns & OO Design...
# 13

> duffymo, I'm still not sure what a "service layer"

> should provide. I would really like to have some

> more info about that. I think you're onto something

> here. We plan on adding a really simple, web-based

> UI to this in the future. I would love to design it

> now so that addition is easy to accomplish.

By service layer, I just mean another interface that is absolutely independent of the UI.

Have you ever used Struts or another web MVC framework? You'll see that Struts has Action classes that take HttpRequest and HttpResponse parameters. The idea is that everything that a user wants to accomplish with your app ends up being expressed in these Action classes. Sounds great, right?

The problem that I see is that it's impossible to use those Actions outside of Struts. They require an HTTP request and response. How do you do that with a Swing UI?

You end up with a lot of Actions, one per use case. It might make sense for them to be related in a single Object.

So the solution is to move all those related Actions into a service interface and have an implementation behind it that deals with domain model and persistence objects to satisfy the request. Have it take parameters that are germane to the thing the user wants to do, not an HTTP request. Return a result that's meaningful to the problem at hand, not an HTTP response. The Struts Action can then contact the service to do something - and so can anyone else who knows about the service.

It's the start of a service oriented architecture that's all the rage. Now your apps can do things by calling services, which are now designed in a way independent of the UI. They don't know anything about the UI layer.

I hope that's illuminating. If not, ask more and either I'll do better or someone else will jump in.

%

duffymoa at 2007-7-14 18:18:35 > top of Java-index,Other Topics,Patterns & OO Design...
# 14

> ter thinking about this over lunch I have a question.

> Your presentation layer uses the methods on the

> domain object to present the data.

> Your DAO layer

> uses the methods on the domain object to store the

> data. Are you using the same methods for both?

You mean do the presentation and persistence layers both call the same getters on an object to access state? Yes.

> Or

> do you have some methods that presentation can't see

> that persistence uses? Such as a persistence

> interface on your domain objects? Or are you using

> reflection or what?

No persistence interface on domain objects. That's the whole idea of one-way coupling: the domain objects don't know that they're persisted.

I'm using Hibernate and Spring. The interface and sample domain object I presented earlier is representative of what I do.

%

duffymoa at 2007-7-14 18:18:35 > top of Java-index,Other Topics,Patterns & OO Design...
# 15

****. I decided to reward duffymo with 1 of the 2 Duke Dollars I allotted for this question. I was going to give the other one to _dnoyeB. Although I think duffymo's replies are leading me in the right direction, I think you both deserve the rewards because the back-and-forth really has helped to shed some light on this topic for me. The problem is that once I rewarded the 1 point, the forums system won't let me reward the other one. It also won't let me add more points to the thread.

_dnoyeB, if you really want the 1 Duke Dollar, I can start another 1 point thread and give it to you. If so, let me know.

jds@ku.edua at 2007-7-21 9:33:46 > top of Java-index,Other Topics,Patterns & OO Design...
# 16

> > ter thinking about this over lunch I have a

> question.

> > Your presentation layer uses the methods on the

> > domain object to present the data.

>

> > Your DAO layer

> > uses the methods on the domain object to store the

> > data. Are you using the same methods for both?

>

> You mean do the presentation and persistence layers

> both call the same getters on an object to access

> state? Yes.

>

> > Or

> > do you have some methods that presentation can't

> see

> > that persistence uses? Such as a persistence

> > interface on your domain objects? Or are you using

> > reflection or what?

>

> No persistence interface on domain objects. That's

> the whole idea of one-way coupling: the domain

> objects don't know that they're persisted.

>

OK, that works given you do one of the following;

1. You expose your domain objects internal state through the normal domain object methods.

2. You use reflection to get at the domain objects internal state without using the domain objects methods.

3. Your domain object was created with 'bugs' inside that allow its internal state to be extracted without going through the domain object methods.

I believe Hibernate does #2. JDO does #3.

I started with JDBC so my initial implementation is a form of a special domain object persistence interface. Its the 'DAO interface' but again this is basically there so the DAO knows how to persist the domain object.

Somewhere the connection between domain object and persistence must be defined. For JDO and Hibernate this is in XML. For my JDBC this was in the interface. The interface seems redundant for JDO/Hibernate.

The more I am involved with persistence the more I think about hands-free methods of persisting data such as reflection. I think it is very clean when you can persist without directly touching the domain object so to speak.

I think I will investigate if its possible to return domain objects from some of my DAO. I'll have to figure out how to keep the query language in the DAO and the domain logic in the domain object as well as needing a bit more help in my presentation layer to produce saves.

Should be a good learining experience.

_dnoyeBa at 2007-7-21 9:33:46 > top of Java-index,Other Topics,Patterns & OO Design...
# 17

> OK, that works given you do one of the following;

>

> 1. You expose your domain objects internal state

> through the normal domain object methods.

I have no idea what you mean by this. What are "normal" methods? I'm using getters and setters after the Java Bean conventions. Is that what you mean by "normal"?

> 2. You use reflection to get at the domain objects

> internal state without using the domain objects

> methods.

No reflection by me. As I've said, I'm using Hibernate. It can gain access even if setters are private (e.g., immutable objects).

> 3. Your domain object was created with 'bugs' inside

> that allow its internal state to be extracted without

> going through the domain object methods.

No bugs. If you mean public data members, then no, I know much better than that.

You might argue that for most people getters and setters aren't much different from public.

> I believe Hibernate does #2. JDO does #3.

I believe you're correct about Hiberate. I don't know about JDO. "bugs"? I don't think you're characterizing it correctly. I thought JDO did byte code enhancement to add persistence to POJOs. I think the spec writers and JDO vendors would take great exception at your use of the phrase "'bugs' inside".

> I started with JDBC so my initial implementation is a

> form of a special domain object persistence

> interface. Its the 'DAO interface' but again this is

> basically there so the DAO knows how to persist the

> domain object.

> Somewhere the connection between domain object and

> persistence must be defined. For JDO and Hibernate

> this is in XML. For my JDBC this was in the

> interface. The interface seems redundant for

> JDO/Hibernate.

Right, it's XML mappings for Hibernate. For JDBC you can implement RowMappers. That's what Spring JDBC does.

> The more I am involved with persistence the more I

> think about hands-free methods of persisting data

> such as reflection. I think it is very clean when

> you can persist without directly touching the domain

> object so to speak.

It's viable now that reflection has been rewritten in Java. Used to be a performance pig when it first came out.

> I think I will investigate if its possible to return

> domain objects from some of my DAO. I'll have to

> figure out how to keep the query language in the DAO

> and the domain logic in the domain object as well as

> needing a bit more help in my presentation layer to

> produce saves.

> Should be a good learining experience.

Try implementing that Shape DAO interface and domain object I posted earlier using JDO. I know I can do it in Hibernate. JDO is just another implementation.

%

duffymoa at 2007-7-21 9:33:46 > top of Java-index,Other Topics,Patterns & OO Design...
# 18

> ****. I decided to reward duffymo with 1 of the 2

> Duke Dollars I allotted for this question. I was

> going to give the other one to _dnoyeB. Although I

> think duffymo's replies are leading me in the right

> direction, I think you both deserve the rewards

> because the back-and-forth really has helped to shed

> some light on this topic for me. The problem is that

> once I rewarded the 1 point, the forums system won't

> let me reward the other one. It also won't let me

> add more points to the thread.

Been a long time since I got a Duke. Thanks.

> _dnoyeB, if you really want the 1 Duke Dollar, I can

> start another 1 point thread and give it to you. If

> so, let me know.

Start another thread, add a Duke, and make the subject call to dnoyeB to come and get it if you're sure you want to award it.

%

duffymoa at 2007-7-21 9:33:46 > top of Java-index,Other Topics,Patterns & OO Design...
# 19

Actually, I have a little bit more for this thread....

Rod,

As I continue abstracting the data access layer so that the business layer doesn't know it's working with Hibernate, I keep running into this question.

Should the business/domain layer understand the concept of transactions/sessions?

I think the answer is actually yes. I don't think we want to make data access SO abstract that data appears to arrive out of thin air (and get saved magically). I think it totally makes since that the domain layer would understand the concept of a transaction, even if our backing datastore were a bunch of flat files. There are times when a user does things (in the domain layer) that they want saved to persistent storage (DB, flat files, whatever) in one atomic move. They also would want to know that if part of it had problems during saving, the whole save could be cancelled.

If we put all transaction management into the DAOs (resulting in transactions starting and ending within public methods such as...

public class HibernateShapeDao implements ShapeDao

{

...

public save(Shape s)

{

// a bad implementation of a Shape DAO, I think

Transaction tx = session.startTransaction();

s.saveOrUpdate();

try

{

tx.commit();

}

catch( HibernateTransaction he )

{

tx.rollback();

}

}

...

}

...then we lose the real power of transactions which is to commit a number of objects as one atomic operation.

So, I think writing DAOs for my Shape classes will be very helpful in abstracting away Hibernate. However, I think I need to keep the concept of a transaction within the Shape viewer/editor Swing GUI. I think I can still hide Hibernate by making a simple Transaction interface that simply has start(), commit() and rollback(). This interface would be EASILY implemented to wrap the Hibernate transaction. After writing this code, I will have absolutely no references to any Hibernate code in my Shape viewer/editor. In fact, I'll implement a very simple DAO factory that does runtime class loading based on some system preference, etc. This should actually allow me to swap out Hibernate and replace it with an XML storage or JDBC backed data store system, without any code change except for a change in an XML properties file or something like that.

Does it sound like I've got the right idea now? I think I'm starting to understand this a lot more. It feels like it makes a lot of sense now.

jds@ku.edua at 2007-7-21 9:33:46 > top of Java-index,Other Topics,Patterns & OO Design...
# 20

> Actually, I have a little bit more for this

> thread....

>

> Rod,

>

> As I continue abstracting the data access layer so

> that the business layer doesn't know it's working

> with Hibernate, I keep running into this question.

>

> Should the business/domain layer understand the

> concept of transactions/sessions?

Yes, not the DAO itself. The service layer is the thing that corresponds to use cases or units of work. That's where transactional boundaries need to be set. That way, if a service uses several DAOs in a single unit of work, they can all participate in a single transaction and be committed or rolled back together.

> I think the answer is actually yes. I don't think we

> want to make data access SO abstract that data

> appears to arrive out of thin air (and get saved

> magically). I think it totally makes since that the

> domain layer would understand the concept of a

> transaction, even if our backing datastore were a

> bunch of flat files. There are times when a user

> does things (in the domain layer) that they want

> saved to persistent storage (DB, flat files,

> whatever) in one atomic move. They also would want

> to know that if part of it had problems during

> saving, the whole save could be cancelled.

Exactly right.

> If we put all transaction management into the DAOs

> (resulting in transactions starting and ending within

> public methods such as...

>

> > public class HibernateShapeDao implements ShapeDao

> {

>...

> public save(Shape s)

>{

>// a bad implementation of a Shape DAO, I think

>Transaction tx = session.startTransaction();

>s.saveOrUpdate();

>try

>{

>tx.commit();

> }

>catch( HibernateTransaction he )

> {

>tx.rollback();

>}

> ...

> }

>

> ...then we lose the real power of transactions which

> is to commit a number of objects as one atomic

> operation.

Yes. This is why the DAO should not be responsible for getting the connection or setting XA boundaries. That's what the service layer does.

> So, I think writing DAOs for my Shape classes will be

> very helpful in abstracting away Hibernate. However,

> I think I need to keep the concept of a transaction

> within the Shape viewer/editor Swing GUI.

No, in the service layer.

> I think I

> can still hide Hibernate by making a simple

> Transaction interface that simply has start(),

> commit() and rollback(). This interface would be

> EASILY implemented to wrap the Hibernate transaction.

> After writing this code, I will have absolutely no

> references to any Hibernate code in my Shape

> viewer/editor. In fact, I'll implement a very

> simple DAO factory that does runtime class loading

> based on some system preference, etc. This should

> actually allow me to swap out Hibernate and replace

> it with an XML storage or JDBC backed data store

> system, without any code change except for a change

> in an XML properties file or something like that.

>

> Does it sound like I've got the right idea now? I

> think I'm starting to understand this a lot more. It

> feels like it makes a lot of sense now.

If you're already sophisiticated enough for Hibernate, perhaps you're also ready for Spring:

http://www.springframework.org

It'll clarify your design a great deal. Have a look at their first MVC example and see if you think it's a good approach for you. I'm betting that their declarative transaction logic and elegant persistence plumbing (with complete Hibernate support) will sell you.

%

duffymoa at 2007-7-21 9:33:46 > top of Java-index,Other Topics,Patterns & OO Design...
# 21

I've attended a short Java users' group talk about the Spring Framework. I'm totally sold. However, some modules of our project are already so far along that I think trying to work Spring into it might turn it into a bit of a Frankenstein project.

Is it possible to cleanly work the Spring Framework into a single module of a large project without making the entire thing a mess?

jds@ku.edua at 2007-7-21 9:33:46 > top of Java-index,Other Topics,Patterns & OO Design...
# 22

> > OK, that works given you do one of the following;

> >

> > 1. You expose your domain objects internal state

> > through the normal domain object methods.

>

> I have no idea what you mean by this. What are

> "normal" methods? I'm using getters and setters

> after the Java Bean conventions. Is that what you

> mean by "normal"?

By normal methods I mean the methods you use for your presentation layer. In your case since you have basically getters and setters this is simple. Unfortunately, 1/2 of my domain objects are not this simple. They contain actual business logic and so the data they expose through their 'normal' business methods is not appropriate for persistence.

>

> > 2. You use reflection to get at the domain

> objects

> > internal state without using the domain objects

> > methods.

>

> No reflection by me. As I've said, I'm using

> Hibernate. It can gain access even if setters are

> private (e.g., immutable objects).

>

hibernate uses relfection.

> > 3. Your domain object was created with 'bugs'

> inside

> > that allow its internal state to be extracted

> without

> > going through the domain object methods.

>

> No bugs. If you mean public data members, then no, I

> know much better than that.

>

when I said 'bugs' I meant the CIA/FBI type of bug, not the software type of bug :) JDO modifies the bytecode so it can listen in on changes to the enhanced objects.

>

> Try implementing that Shape DAO interface and domain

> object I posted earlier using JDO. I know I can do

> it in Hibernate. JDO is just another

> implementation.

>

> %

Basically I am. My program is a graphic editor of sorts. I do have a shape class. I am changeing over my graphics objects but my other business objects i am holding off on because they are more complicated.

Its a bit disappointing that I now have to implement the full set of business objects for each persistence technology. I hate to replicate the business logic but the only way my DAOs can directly hand out business classes is if they are enhanced by JDO. And I can't have JDO enhancing the business classes of my JDBC implementation. I wonder if I can wrap a general business object implementation with a JDO business object implementation so I don't have to replicate the business logic.

_dnoyeBa at 2007-7-21 9:33:46 > top of Java-index,Other Topics,Patterns & OO Design...
# 23

> By normal methods I mean the methods you use for your

> presentation layer. In your case since you have

> basically getters and setters this is simple.

> Unfortunately, 1/2 of my domain objects are not this

> simple. They contain actual business logic and so

> the data they expose through their 'normal' business

> methods is not appropriate for persistence.

Not sure I'm following you here, but I'll accept it.

> hibernate uses relfection.

Yes.

> when I said 'bugs' I meant the CIA/FBI type of bug,

> not the software type of bug :) JDO modifies the

> bytecode so it can listen in on changes to the

> enhanced objects.

OK, "bug" is an overloaded word, so i was confused. Now it's clear.

> Basically I am. My program is a graphic editor of

> sorts. I do have a shape class. I am changeing over

> my graphics objects but my other business objects i

> am holding off on because they are more complicated.

>

> Its a bit disappointing that I now have to implement

> the full set of business objects for each persistence

> technology.

I absolutely do not understand why this is. You should not have to reimplement the business objects for each persistence technology. If you do, then I'd argue that your design is flawed and needs to be revisited.

> I hate to replicate the business logic

> but the only way my DAOs can directly hand out

> business classes is if they are enhanced by JDO. And

> I can't have JDO enhancing the business classes of my

> JDBC implementation. I wonder if I can wrap a

> general business object implementation with a JDO

> business object implementation so I don't have to

> replicate the business logic.

I don't like it, but that's me. I don't believe a wrapper should be necessary.

%

duffymoa at 2007-7-21 9:33:46 > top of Java-index,Other Topics,Patterns & OO Design...
# 24

I'm still not sure what the service layer has in it.

Let's say I have...

package model;

public class Point extends Serializable

{

private Integer id;

private Integer x;

private Integer y;

public Point()

// constructor, getters and setters omitted

}

package model;

public class Shape extends Serializable

{

private Integer id;

private Set<Point> points;

private String name;

// constructor, getters and setters omitted

}

... as my data model.

So I would have something like...

package dao;

public interface GenericDAO <T, PK extends Serializable>

{

// taken from www-128.ibm.com/developerworks/java/library/j-genericdao.html

public PK create(T newInstance);

public T read(PK id);

public void update(T transientObject);

public void delete(T persistentObject);

}

package dao;

public interface PointDAO extends GenericDAO<Point,Integer>

{

public Integer getX(Point p);

public Integer getY(Point p);

// and some 'finder' methods

}

package dao;

public interface ShapeDAO extends GenericDAO<Shape,Integer>

{

public Set<Point> getPoints(Shape s);

public String getName(Shape s);

}

... for DAO interfaces, right?

And then something like...

package dao.impl;

public class HibernateShapeDAO implements ShapeDAO

{

public String getName(Shape s)

{

return s.getName();

}

public Set<Point> getPoints(Shape s)

{

HibernateUtil.getCurrentSession().lock(s,LockMode.NONE);

Set<Point> points = s.getPoints();

// force the data to be loaded into the Set items

if(!points.isEmpty())

{

points.iterator().next();

}

// to keep the Session from getting too large

HibernateUtil.getCurrentSession.evict(s);

return points;

}

}

...for a Hibernate-based implementation, right?

When my GUI (which has a data model full of Shape objects) needs to get the Set<Point> for a shape (myShape) it would call DaoFactory.getShapeDAO().getPoints(myShape)?

Where does the service come in? If you could explain it in the context of an action listener, that would be great. In other words, lets say a user double-clicked on a Shape name, which results in the GUI loading a presenting a rendered Shape object. So, the action listener needs to get the Points associated with the shape.

I definitely owe you guys a lot more Duke Dollars. Thanks to both of you.

jds@ku.edua at 2007-7-21 9:33:46 > top of Java-index,Other Topics,Patterns & OO Design...
# 25

There are many ways to do it. Just make it work, then give a name to the architecture you end up with. Thats what I would recommend.

Anyway.

I believe if I understand correctly, a DAO is used to return your domain object, but not to return properties about your domain object.

so this is correct;

package dao;

public interface GenericDAO <T, PK extends Serializable>

{

// taken from www-128.ibm.com/developerworks/java/library/j-genericdao.html

public PK create(T newInstance);

public T read(PK id);

public void update(T transientObject);

public void delete(T persistentObject);

}

but this is not really a dao;

package dao;

public interface ShapeDAO extends GenericDAO<Shape,Integer>

{

public Set<Point> getPoints(Shape s);

public String getName(Shape s);

}

You should be able to ask the shape directly for its name and points.

Sometimes you dont have a service layer as the dao itself can perform what the service layer offers. Its best if you do not force a service layer on yourself. Just try to maintain seperation. Do not put any DAO code in your presentation layer. See where that takes you.

Dont worry about the duke dollars. I havent received or given any out for about 2-3 years now since Sun first started screwing around with the forum.

_dnoyeBa at 2007-7-21 9:33:46 > top of Java-index,Other Topics,Patterns & OO Design...
# 26

> I believe if I understand correctly, a DAO is used to

> return your domain object, but not to return

> properties about your domain object.

I was starting to think this. But then how would I deal with the fact that Hibernate can throw a LazyInstatiationException when I ask a shape for it's points directly?

jds@ku.edua at 2007-7-21 9:33:46 > top of Java-index,Other Topics,Patterns & OO Design...
# 27

I think what duffymo has viewed as his presentation layer is the same as what I have been viewing as my domain layer. I think this because his presentation layer is using objects that consist mostly of getters/setters but actually performs things more complicated than just getting and setting (I assume). My domain layer is using objects that consist mostly of getters/setters but actually perform things more complicated than just getting and setting.

This also makes his domain layer like my DAO layer. His domain objects are mostly getters/setters while my DAOs are mostly getters/setters.

His getter/setter objects are produced by his DAO layer. My getter/setter objects are produced by my ORM/JDBC layer.

This is a big help in my understanding why JDO expects to be enhancing the domain objects. What I have been calling my DAOs are actually my domain objects. Its just that I have more than one domain.

I think its also true that I don't have any DAOs. I have been wanting to merge my XML saving scheme with my datastore saving scheme. I think I am seeing why this has been so hard.

_dnoyeBa at 2007-7-21 9:33:46 > top of Java-index,Other Topics,Patterns & OO Design...
# 28

> > I believe if I understand correctly, a DAO is used

> to

> > return your domain object, but not to return

> > properties about your domain object.

>

> I was starting to think this. But then how would I

> deal with the fact that Hibernate can throw a

> LazyInstatiationException when I ask a shape for it's

> points directly?

I have had to deal with this in JDO. If I dont turn on non-transactional read, then I start reading through a collection that is not fully loaded and JDO tries to load it up, it will throw an exception due to the access being outside of a transaction.

In JDO there are a few ways to solve this. My strategy is to enable what is called non-transactional read. This means I can read from objects while they are out of a transaction. Next, I make sure my objects are fully loaded when they are returned from the datastore.

Now I know you will want to load lazily and not eagerly. That is why the lazy logic has to be baked into your GUI. you can't rely on ORM to load lazily outside of a transaction. ORM really expects all of its business to be done within a transaction. its tough to accomplish this in a GUI.

Maybe hibernate has a similar option you can enable. But dont forget to prefetch the whole children. this is rather heavy since its the whole object graph of the children too.

Another way is to eagerly load the children's basic properties like name/ color, etc. by using non-transactional reading and ensuring those are loaded. But when other properties are read such as getChildren(), have the child start a transaction and read. but this means your

getChildren() method will now be capable of throwing exceptions which I think should be checked exceptions since db can close at any time.

basically have a method on your domain object called getChildren() and within that method start a transaction. Or call the service layer and request the children from it. Basically seperate logically the auto-loaded properties of your domain objects from the lazily loaded ones.

_dnoyeBa at 2007-7-21 9:33:46 > top of Java-index,Other Topics,Patterns & OO Design...
# 29

> There are many ways to do it. Just make it work,

> then give a name to the architecture you end up with.

> Thats what I would recommend.

I'd recommend that the OP go back and re-read what I wrote about the motivation for a service layer (e.g., UI independence, easier testability, etc.) Many ways to do things, but I've provided a good reason for doing it with a service layer.

>

> Anyway.

>

> I believe if I understand correctly, a DAO is used to

> return your domain object, but not to return

> properties about your domain object.

What's the difference? How are they separate?

> so this is correct;

I don't believe it is.

> package dao;

> public interface GenericDAO <T, PK extends

> Serializable>

> {

> // taken from

> www-128.ibm.com/developerworks/java/library/j-generic

> ao.html

>public PK create(T newInstance);

> public T read(PK id);

>public void update(T transientObject);

> public void delete(T persistentObject);

> }

>

>

> but this is not really a dao;

I say it is. IBM says it is. What reason do you have for saying it's not?

The only thing I'd disagree with is the explicit reliance on PK in this interface. I'd internalize the PK.

> > package dao;

> public interface ShapeDAO extends

> GenericDAO<Shape,Integer>

> {

>public Set<Point> getPoints(Shape s);

> public String getName(Shape s);

> }

>

getName() sounds like it should be a method on Shape itself, not part of the DAO. Your DAO example makes less sense to me than the one the OP/IBM posted.

> You should be able to ask the shape directly for its

> name and points.

Right. So why is it in your DAO? This argument is counter to what you posted.

> Sometimes you dont have a service layer as the dao

> itself can perform what the service layer offers.

I'll agree that the service layer might do little more than call the DAO's method to access data, but I'd still prefer to hide it behind an interface.

> Its best if you do not force a service layer on yourself.

I'd argue that it's not forcing anything, and I've cited reasons why it might be beneficial. All dnoyeB has offered is "because I said so".

> Just try to maintain seperation. Do not

> put any DAO code in your presentation layer. See

> where that takes you.

That's exactly what he has to do if he does not have a service layer. The listener in the UI will call the DAO directly. Isn't this 180 degrees from your previous argument to "not force a service layer"?

%

duffymoa at 2007-7-21 9:33:46 > top of Java-index,Other Topics,Patterns & OO Design...
# 30

> I'm still not sure what the service layer has in it.

I'll try again.

>

> Let's say I have...

I looked at your code quickly - looks fine.

> ... for DAO interfaces, right?

Looks pretty good. I only have minor disagreements. (e.g., "getName()" seems too granular to me. I think it belongs with Shape.) We're pretty much together here.

>

> And then something like...

> ...for a Hibernate-based implementation, right?

Right.

> Where does the service come in?

The UI would not call the DAO factory. It would ask the service for the set of points. It's the service layer that knows about the DAO and its factory. It knows about the model objects. It deals with the persistence layer on the UI's behalf.

> If you could explain

> it in the context of an action listener, that would

> be great. In other words, lets say a user

> double-clicked on a Shape name, which results in the

> GUI loading a presenting a rendered Shape object.

> So, the action listener needs to get the Points

> associated with the shape.

I'll agree that the query for a list of Shapes seems so trivial that the service hardly seems unnecessary. It makes more sense on a more complex write operation. Let's say you have a Shape that was really a complex tree of graphic elements that you wanted to persist. Perhaps there's another associated object with its own DAO that you have to persist in the same unit of work. You know that a DAO cannot know when it's part of a larger transaction, so you can't begin/end a transaction within a DAO.

This is where the service layer comes in. It knows about transactions and units of work. It starts the transaction, orchestrates several DAOs to perform the write operations, and commits the transaction if all is well. You cannot do that with a single DAO. You want to hide all that from users because, after all, they just want to save their object, right?

So stay with that model even in the simple case where you're querying for a list. You might not need it, but there are great benefits to this design.

So your service package will have interfaces and impls, must like the persistence package. If your apps are just web-based CRUD operations on relational tables you might find that your service interface methods mirror your persistence layer. Don't take this as a sign that you should dispense with the service layer. That's where transactions are handled, not in the persistence layer.

I have a fundamental disagreement with dnoyeB here. You read my arguments and his and decide for yourself which ones work better.

> I definitely owe you guys a lot more Duke Dollars.

Don't worry about it.

> Thanks to both of you.

Thanks to you. Your question has been excellent - most interesting and educational for me. I've enjoyed the discussion a great deal. This is the way this forum is supposed to work.

%

duffymoa at 2007-7-21 9:33:51 > top of Java-index,Other Topics,Patterns & OO Design...
# 31

> > There are many ways to do it. Just make it work,

> > then give a name to the architecture you end up

> with.

> > Thats what I would recommend.

>

> I'd recommend that the OP go back and re-read what I

> wrote about the motivation for a service layer (e.g.,

> UI independence, easier testability, etc.) Many ways

> to do things, but I've provided a good reason for

> doing it with a service layer.

>

You are always going to have some service layer somewhere. The first domain object will have to come from that. Its unavoidable if you focus on seperating your layers as I suggested. What I am actually suggesting is he start writing code. Lots of understanding comes from getting your feet wet. You can't see it all up front.

> >

> > Anyway.

> >

> > I believe if I understand correctly, a DAO is used

> to

> > return your domain object, but not to return

> > properties about your domain object.

>

> What's the difference? How are they separate?

>

> > so this is correct;

>

> I don't believe it is.

>

At this point you begin to misread my post. So I won't comment on it except to say that I agree with you and don't understand how you thought I was saying the things you are disagreeing with.

> > Sometimes you dont have a service layer as the dao

> > itself can perform what the service layer offers.

>

> I'll agree that the service layer might do little

> more than call the DAO's method to access data, but

> I'd still prefer to hide it behind an interface.

>

Me to. I think I mixed my terms a bit.

> > Its best if you do not force a service layer on

> yourself.

>

> I'd argue that it's not forcing anything, and I've

> cited reasons why it might be beneficial. All dnoyeB

> has offered is "because I said so".

>

I did not recommend that he use or not use a service layer. I recommended that he get to work and see where layer seperation takes him.

If you take away my layer naming, my architecture is the same as yours. I didn't plan it that way, but if you focus on layer seperation its where you end up.

> > Just try to maintain seperation. Do not

> > put any DAO code in your presentation layer. See

> > where that takes you.

>

> That's exactly what he has to do if he does not have

> a service layer. The listener in the UI will call

> the DAO directly. Isn't this 180 degrees from your

> previous argument to "not force a service layer"?

>

I think the OP is missing the fact that the service layer's real job is to seperate DAO from presentation.

duffymo, do you

1. Inject your domain objects into your presentation layer. Where your domain objects update/delete themselves.

2. Inject your service layer into your presentation layer and let your presentation layer use the service layer to obtain/update/delete the domain objects?

_dnoyeBa at 2007-7-21 9:33:51 > top of Java-index,Other Topics,Patterns & OO Design...
# 32

> I have a fundamental disagreement with dnoyeB here.

> You read my arguments and his and decide for

> yourself which ones work better.

>

Actually we agree. Like I was saying to the OP, just seperate your layers and you will end up with the proper result. I separated my layers. The argument I have been having with duffymo is because I was using the wrong names for my layers. I do have a service layer I just did not see it. In some places I called this my TopDomain but its really a service layer.

So go with what duffymo has said because his terms have been correct all along.

_dnoyeBa at 2007-7-21 9:33:51 > top of Java-index,Other Topics,Patterns & OO Design...
# 33

> You are always going to have some service layer

> somewhere.

Yes, but don't you see that you recommended that he use the DAO, I'm recommending an explicit service layer, and there's a difference between the two that has to do with transactions? You don't have a service layer as I'm defining it.

> The first domain object will have to come

> from that. Its unavoidable if you focus on

> seperating your layers as I suggested. What I am

> actually suggesting is he start writing code.

Who's telling him not to write code? Nothing new there.

> Lots

> of understanding comes from getting your feet wet.

> You can't see it all up front.

But I'm telling him something that he can see up front and explaining why it might be important. You just keep saying "because I said so".

> At this point you begin to misread my post. So I

> won't comment on it except to say that I agree with

> you and don't understand how you thought I was saying

> the things you are disagreeing with.

OK.

> Me to. I think I mixed my terms a bit.

No, you explicitly said "call the DAO and get it from the DAO factory". That's not agreeing, and not mixing up terms.

>

> I did not recommend that he use or not use a service

> layer. I recommended that he get to work and see

> where layer seperation takes him.

Yes, you said start with the DAO. That's not the service layer that I'm talking about.

> If you take away my layer naming, my architecture is

> the same as yours.

No, it's not. You don't understand the difference if you insist on this.

> I didn't plan it that way, but if

> you focus on layer seperation its where you end up.

> I think the OP is missing the fact that the service

> layer's real job is to seperate DAO from

> presentation.

No, the service layer's job is to provide a real service independent of any presentation.

> 1. Inject your domain objects into your presentation

> layer. Where your domain objects update/delete

> themselves.

No, they come from the service. No injection.

> 2. Inject your service layer into your presentation

> layer and let your presentation layer use the service

> layer to obtain/update/delete the domain objects?

If the presentation needs to call a service then the implementation can be injected. The service layer manages all the acquisition and changes to objects that accomplish the user's request and sends back the appropriate response for display.

%

duffymoa at 2007-7-21 9:33:51 > top of Java-index,Other Topics,Patterns & OO Design...
# 34

> At this point you begin to misread my post. So I

> won't comment on it except to say that I agree with

> you and don't understand how you thought I was saying

> the things you are disagreeing with.

Look at your post #25:

"You should be able to ask the shape directly for its name and points.

Sometimes you dont have a service layer as the dao itself can perform what the service layer offers. Its best if you do not force a service layer on yourself. Just try to maintain seperation. Do not put any DAO code in your presentation layer. See where that takes you."

C'mon, we don't agree. You said so here. I'm not misreading anything.

I think you don't understand the significance of the service layer.

%

duffymoa at 2007-7-21 9:33:51 > top of Java-index,Other Topics,Patterns & OO Design...
# 35

> > At this point you begin to misread my post. So I

> > won't comment on it except to say that I agree

> with

> > you and don't understand how you thought I was

> saying

> > the things you are disagreeing with.

>

> Look at your post #25:

>

> "You should be able to ask the shape directly for its

> name and points.

>

> Sometimes you dont have a service layer as the dao

> itself can perform what the service layer offers. Its

> best if you do not force a service layer on

> yourself. Just try to maintain seperation. Do not

> put any DAO code in your presentation layer. See

> where that takes you."

>

> C'mon, we don't agree. You said so here. I'm not

> misreading anything.

>

> I think you don't understand the significance of the

> service layer.

>

> %

I don't think you understand that peoples level of knowledge can change as mine has over this thread. You are still attempting to argue against my former understanding. I am past that.

To the OP, I am just now reworking my architecture and am experiencing the exact same problem that you are.

My System object is a drawing that has a name. The name is displayed in a tree and when double clicked will cause to open the associated drawing in an editor.

Looks simple enough. The tricky part is to use the same object in the tree as in the drawing. JDO does not make it easy to load stuff into objects outside of a transaction. gotta figure out where to put the transaction.

_dnoyeBa at 2007-7-21 9:33:51 > top of Java-index,Other Topics,Patterns & OO Design...
# 36

> I don't think you understand that peoples level of

> knowledge can change as mine has over this thread.

> You are still attempting to argue against my former

> understanding. I am past that.

How am I supposed to tell that?

> To the OP, I am just now reworking my architecture

> and am experiencing the exact same problem that you

> are.

So why do you keep arguing against what I'm offering if yours doesn't even work?

> My System object is a drawing that has a name. The

> name is displayed in a tree and when double clicked

> will cause to open the associated drawing in an

> editor.

>

> Looks simple enough. The tricky part is to use the

> same object in the tree as in the drawing. JDO does

> not make it easy to load stuff into objects outside

> of a transaction. gotta figure out where to put the

> transaction.

Why do you need a transaction for a query?

I think the transaction belongs in the service tier. Not tricky at all. Not much to figure out after I've said it time after time in this thread.

Here's the way I'd see that flow:

Make Shape immutable, for starters.

(1) UI makes a request for a List of Shapes to its Controller.

(2) Controller routes the request to the appropriate Service to get a List of Shapes that satisfy your criteria.

(3) Service marshalls the appropriate DAO to obtain the List of Shapes.

(4) DAO queries the database, SELECTs the List of Shapes, and returns it to the Service.

(5) Service hands the List of Shapes off to the Controller.

(6) Controller gives the List of Shapes to the UI for display in the tree.

I think the trickier part is lazy loading and caching. If that tree happens to contain 10,000 Shapes when every leaf is displayed you might have a problem, because you don't want to bring all those Shapes nito memory at the same time. If the tree is closed, all your UI displays are the root nodes. When the user clicks on a node to open it up, you want the UI to display only the open nodes. THAT'S tricky.

Same stuff applies, but if the Service caches the List of Shapes and only returns the ones you need you can save yourself a network hop for each subsequent request.

%

duffymoa at 2007-7-21 9:33:51 > top of Java-index,Other Topics,Patterns & OO Design...
# 37

> > I don't think you understand that peoples level of

> > knowledge can change as mine has over this thread.

> > You are still attempting to argue against my

> former

> > understanding. I am past that.

>

> How am I supposed to tell that?

>

Perhaps when I suggested the OP listen to your statements because I agree with them all?

> > To the OP, I am just now reworking my architecture

> > and am experiencing the exact same problem that

> you

> > are.

>

> So why do you keep arguing against what I'm offering

> if yours doesn't even work?

>

I am not arguing against your architecture. In any event, this part of my architecture is not related to lazy loading. They are two different issues.

> > My System object is a drawing that has a name.

> The

> name is displayed in a tree and when double clicked

> will cause to open the associated drawing in an

> editor.

>

> Looks simple enough. The tricky part is to use the

> same object in the tree as in the drawing. JDO

> does

> not make it easy to load stuff into objects outside

> of a transaction. gotta figure out where to put the

> transaction.

>

> Why do you need a transaction for a query?

>

You dont really. What I mean is that you can throw an exception here. GUIs are not very exception friendly nor is it nice to block them. If you pre-load everything is simple.

> I think the transaction belongs in the service tier.

> Not tricky at all. Not much to figure out after

> I've said it time after time in this thread.

>

I agree with that.

> Here's the way I'd see that flow:

>

> Make Shape immutable, for starters.

>

> (1) UI makes a request for a List of Shapes to its

> Controller.

> (2) Controller routes the request to the appropriate

> Service to get a List of Shapes that satisfy your

> criteria.

> (3) Service marshalls the appropriate DAO to obtain

> the List of Shapes.

> (4) DAO queries the database, SELECTs the List of

> Shapes, and returns it to the Service.

> (5) Service hands the List of Shapes off to the

> Controller.

> (6) Controller gives the List of Shapes to the UI for

> display in the tree.

>

> I think the trickier part is lazy loading and

> caching. If that tree happens to contain 10,000

> Shapes when every leaf is displayed you might have a

> problem, because you don't want to bring all those

> Shapes nito memory at the same time. If the tree is

> closed, all your UI displays are the root nodes.

> When the user clicks on a node to open it up, you

> want the UI to display only the open nodes. THAT'S

> tricky.

>

This is exactly his problem. His architectural questions were educational, but this lazy loading is his main issue. I dont think the fixed arch will assist the lazy loading problem directly.

What I do is run a new query when the user expands a node. It stalls there for a second, but you have to make the trade somewhere.

You may have to create a 'smart' tree that can load as it scrolls if you have a huge tree. but if its that big it probably should not be a tree.

_dnoyeBa at 2007-7-21 9:33:51 > top of Java-index,Other Topics,Patterns & OO Design...
# 38

A service layer does not address the lazy loading issue, that's for sure. If you use Hibernate you get its caching and lazy loading features out of the box. That's why writing a custom JDBC solution isn't always the best way to go. Caching and lazy loading take a lot of code to get right.

%

duffymoa at 2007-7-21 9:33:51 > top of Java-index,Other Topics,Patterns & OO Design...
# 39

> Here's the way I'd see that flow:

>

> Make Shape immutable, for starters.

>

> (1) UI makes a request for a List of Shapes to its

> Controller.

> (2) Controller routes the request to the appropriate

> Service to get a List of Shapes that satisfy your

> criteria.

> (3) Service marshalls the appropriate DAO to obtain

> the List of Shapes.

> (4) DAO queries the database, SELECTs the List of

> Shapes, and returns it to the Service.

> (5) Service hands the List of Shapes off to the

> Controller.

> (6) Controller gives the List of Shapes to the UI for

> display in the tree.

I guess this didn't seem right to me since the UI model has a bunch of Shapes (persistent objects) on which it could easily call getChildren(). Instead, you're asking me to call dataService.getChildren(Shape persistentObj). It seems like I'm throwing away all of the gains of using an ORM technology. Any thoughts?

jds@ku.edua at 2007-7-21 9:33:51 > top of Java-index,Other Topics,Patterns & OO Design...
# 40

My domain objects are packaged within another class, along with the tranxastion/query handler. I consider this class that houses the domain object and the service methods to be part of the UI at this point. And when I take a close look, I think its fitting.

So what I have is like this

//The tree that shows the nodes (UI)

class Tree {

doTree(){

Project project = getProject();

List l = project.getChildren();//throws exception

showNodes(l);

}

}

//class below represents a "project" to the UI (UI)

//this class fires events and handles other UI relates stuff

//for instance, if more children are added will fire event for Tree to hear

//it has in it the ProjHndlr which can get info from the db as needed

class Project{

private ProjHndlr proj;

public List getChildren() throws SomeException {

try {

return proj.getChildren();

}catch(JDOException e){

throw SomeException(e)

}

}

}

//the object capable of getting stuff from the db

//this is basically my transaction/query managing object.

class ProjHndlr {

private Object projectID;

private JDOPersistenceManager pm;

public List getChildren() throws JDOException {

//SQL or JDOQL or JDO XAction.

}

}

class Child {

String name;

int x;

int y;

Object childID;

}

here child is a domain object clearly. However, ProjHndlr is also basically a domain object. its just that _all_ of its access requires transactions/queries so there is no point passing around a ProjDomain object by itself since each access will require the pm anyway. So i package the ProjDomain with the PersistenceManager and provide an interface that makes it look like an exception throwing domain object.

P.S. The gains of ORM technology is in the mapping of objects to the database. Its not in the appearant ability to treat these database concious objects as if their data materializes out of nowhere.

_dnoyeBa at 2007-7-21 9:33:51 > top of Java-index,Other Topics,Patterns & OO Design...
# 41

> I guess this didn't seem right to me since the UI

> model has a bunch of Shapes (persistent objects) on

> which it could easily call getChildren(). Instead,

> you're asking me to call

> dataService.getChildren(Shape persistentObj). It

> seems like I'm throwing away all of the gains of

> using an ORM technology. Any thoughts?

This is a complicated question, and I'm not sure I can give it justice here.

If your design for Shape has a List of child Shapes, I'm not saying that you should ask for a List of children every time you want to traverse a Shape tree. I think Hibernate deals with lazy loading issues like this.

When you query for a particular Spape, and if you've mapped it as a parent/child relationship, AND you turn lazy loading on in Hibernate, I believe Hibernate will query for the children when you try to access them. Obviously, this is a long-running transaction where a Hibernate session will have to be open while you're interacting with the Shape object(s).

It's something that you'd have to work out with Hibernate. Yes, there are trade-offs between memory and network calls, but those are with you no matter how you choose to do this.

I think this question is a deep one, more than I can dash off the top of my head. Either someone smarter than me will have to jump in, or you'll have to start digging into how you can accomplish this with Hibernate. I know it's designed with this sort of thing in mind, but I don't have it firmly in hand so I can just tell you how to do it.

%

%

duffymoa at 2007-7-21 9:33:51 > top of Java-index,Other Topics,Patterns & OO Design...
# 42

So is the question being asked here if you should perform the query of loading children during the creation of the Shape or perform this query sometime after the shape is created?

Or are you asking about how many objects the UI should have to manipulate/ know about in order to get at the children?

Or both?

_dnoyeBa at 2007-7-21 9:33:51 > top of Java-index,Other Topics,Patterns & OO Design...
# 43

I think I'm actually starting to head down a different line of questioning. duffymo hit on the meat of the problem when he said "Obviously, this is a long-running transaction where a Hibernate session will have to be open while you're interacting with the Shape object(s)." I think I have a good understanding of how to layer my application now. The problem now turns to session management.

I think I have things under control now.

I have a bunch of UI class, one of which is a ListModel holding a ton of persistent objects. I have a ShapeDataService object that basically provides methods such as getRootShape() which convert UI requests into calls to DAO objects that know how to get the shapes from the DB. My ShapeDataService is actually an interface. I have an implementation HibernateShapeDataService that owns a Hibernate Session. That way the UI knows nothing about Sessions or Hibernate. The interface also has methods such as saveCurrentShapeTree(). The Hibernate-based impl then sets up a transaction, calls saveOrUpdate(shape) on a bunch of shapes, and returns.

I did a quick and easy check to see that nowhere in any of my UI classes do I have any imports from the Hibernate JAR files or any references to the Hibernate-based impl of my ShapeDataService interface. Everything seems nicely separated now.

Thanks for all of the helpful discussion/arguing/debating/etc.

jds@ku.edua at 2007-7-21 9:33:51 > top of Java-index,Other Topics,Patterns & OO Design...
# 44

> I think I'm actually starting to head down a

> different line of questioning. duffymo hit on the

> meat of the problem when he said "Obviously, this is

> a long-running transaction where a Hibernate session

> will have to be open while you're interacting with

> the Shape object(s)." I think I have a good

> understanding of how to layer my application now.

> The problem now turns to session management.

>

> I think I have things under control now.

>

> I have a bunch of UI class, one of which is a

> ListModel holding a ton of persistent objects. I

> have a ShapeDataService object that basically

> provides methods such as getRootShape() which convert

> UI requests into calls to DAO objects that know how

> to get the shapes from the DB. My ShapeDataService

> is actually an interface. I have an implementation

> HibernateShapeDataService that owns a Hibernate

> Session. That way the UI knows nothing about

> Sessions or Hibernate. The interface also has

> methods such as saveCurrentShapeTree(). The

> Hibernate-based impl then sets up a transaction,

> calls saveOrUpdate(shape) on a bunch of shapes, and

> returns.

>

> I did a quick and easy check to see that nowhere in

> any of my UI classes do I have any imports from the

> Hibernate JAR files or any references to the

> Hibernate-based impl of my ShapeDataService

> interface. Everything seems nicely separated now.

>

> Thanks for all of the helpful

> discussion/arguing/debating/etc.

I think you have implemented the DAO pattern well. If you havent seen it here is sun's description

http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html

You can setup your environment so that the different layers are compiled into different jar files. This way you can be 100% certain of independence. Since I use Eclipse I use different projects which equates to the same thing.

_dnoyeBa at 2007-7-21 9:33:51 > top of Java-index,Other Topics,Patterns & OO Design...
# 45

> So is the question being asked here if you should

> perform the query of loading children during

> the creation of the Shape

That's eager loading.

> or perform this query sometime after the shape is created?

That's lazy loading.

The choice is up to you, and the decision depends on a tradeoff between memory (space) and network roundtrips (time).

> Or are you asking about how many objects the UI

> should have to manipulate/ know about in order to get

> at the children?

Again it depends on the design. If you model Shape with a List of child Shapes, each of which in turn can have their own List of grandchild Shapes, then it should be the root Shape that you're dealing with.

%

duffymoa at 2007-7-21 9:33:56 > top of Java-index,Other Topics,Patterns & OO Design...
# 46

> I think I'm actually starting to head down a

> different line of questioning. duffymo hit on the

> meat of the problem when he said "Obviously, this is

> a long-running transaction where a Hibernate session

> will have to be open while you're interacting with

> the Shape object(s)." I think I have a good

> understanding of how to layer my application now.

> The problem now turns to session management.

"Hibernate In Action" has a fine discussion of the problem in section 8.2 "Implementing Application Transactions", pages 320-330. I recommend that you give it a look.

%

duffymoa at 2007-7-21 9:33:56 > top of Java-index,Other Topics,Patterns & OO Design...
# 47

> "Hibernate In Action" has a fine discussion of the

> problem in section 8.2 "Implementing Application

> Transactions", pages 320-330. I recommend that you

> give it a look.

Thanks for the reference. I'll steal that book from my coworker's desk immediately.

Oops, I spoke to soon. He just got back from lunch.

jds@ku.edua at 2007-7-21 9:33:56 > top of Java-index,Other Topics,Patterns & OO Design...
# 48

After re-reading the Java Blueprints article about the DAO pattern, I think I've come to a realization. Part of my misunderstanding about how to implement DAO using Hibernate stems from Hibernate's internal support for lazy-loading and how (I think) that is at odds with one of the goals of the DAO pattern. From the Java Blueprints DAO pattern description, you see that the DAO pattern "Centralizes All Data Access into a Separate Layer". When you have a persistent object that has a getter to retrieve a lazy-loaded collection (such as getChildren()), you are leaking some of the data access code into any layer where that getter might be called. Of course, in Hibernate, as long as a Session is open and the persistent object is associated with it, the getter will work without any knowledge of it requiring "data access". However, it will still require DB access (and possibly network access, depending on where the DB is).

I think this has confused me quite a bit. So, using lazy-loaded collections in Hibernate, you can't really run away from this without making a bunch of DTO classes that mirror the persistent classes and never passing an instance of a persistent class above the service layer.

I'm fine with this. I just needed to verbalize it to get it straight (and possibly for the help of other readers out there).

jds@ku.edua at 2007-7-21 9:33:56 > top of Java-index,Other Topics,Patterns & OO Design...
# 49

from the point of view of clients of the object, they don't know or care that you're lazy loading and having to go back to the database to get that object. for all they know you've got them in a collection under the covers and the parent object is just doling them out. (they only know or care if the interaction between the parent and the database becomes so slow and chatty that the "time for space" trade-off screws over your service level agreement).

with that DAO you have put all your data acces into a defined layer. why does lazy loading screw that over? you've got the reference to the parent. what else do you need?

i think DTOs are an anti-pattern. you should not have to maintain two parallel hierarchies of objects, all with the same attributes and similar names, just for the sake of some layering purity.

%

duffymoa at 2007-7-21 9:33:56 > top of Java-index,Other Topics,Patterns & OO Design...
# 50

> from the point of view of clients of the object, they

> don't know or care that you're lazy loading and

> having to go back to the database to get that object.

> for all they know you've got them in a collection

> under the covers and the parent object is just

> doling them out. (they only know or care if the

> interaction between the parent and the database

> becomes so slow and chatty that the "time for space"

> trade-off screws over your service level

> agreement).

I completely agree with this. I don't want my UI classes to know or care about where the set of child objects comes from. In fact, I don't want my UI classes to even know the concept of a database or files or whatever.

> with that DAO you have put all your data acces into a

> defined layer. why does lazy loading screw that

> over? you've got the reference to the parent. what

> else do you need?

I just don't like that you have to work with the assumption that a Hibernate Session is always open. I could use a DAO object to do a shapeDAO.getChildren(shape) (and make sure that the DAO object is associated with a Session), but Hibernate gives me the ability to simply call shape.getChildren(). However, if I don't have a Session open, Hibernate is going to throw a fit.

> i think DTOs are an anti-pattern. you should not

> have to maintain two parallel hierarchies of objects,

> all with the same attributes and similar names, just

> for the sake of some layering purity.

I agree with this as well. I've never liked the idea of mirroring any part of my code tree.

jds@ku.edua at 2007-7-21 9:33:56 > top of Java-index,Other Topics,Patterns & OO Design...
# 51

> I think this has confused me quite a bit. So, using

> lazy-loaded collections in Hibernate, you can't

> really run away from this without making a bunch of

> DTO classes that mirror the persistent classes and

> never passing an instance of a persistent class above

> the service layer.

>

The truth is, just because you hide the transaction and query inside of a runtime exception and make the object look like an ordinary object, you still experience the delay of the database call as well as the risk of throwing database related exceptions during that call. Its a facade. But you can use Hibernate/JDO without hiding/ignoring exception throwing calls.

When using DAO and DTO you know which objects can throw exceptions (DAO) and which can not (DTO).

DTO are nasty when most of your calls throw exceptions. That is when the domain objects data is lazy loaded or instantly stored. Indeed its just an anti pattern. The DTO becomes nothing more than an ID for calls on the DAO.

But DTOs can really shine when your UI will perform many actions on your domain object between stores. For instance I have a CAD like editor where all the objects being manipulated are DTOs. When the user pushes save, the 'topmost' DTO is passed into a DAO and the whole graph is stored.

But Note that my domain objects are expressed by interfaces. the implementing class of the interface may be solely a DTO, or it may be a DAO+DTO, or just a DAO. The user of the domain objects can't tell except to know which domain methods throw exceptions and which do not.

To be honest I have not been able to find the proper name for some of my classes that I call DAOs. They not only return domain objects, but they themselves implement a domain interface and behave like a domain object.

_dnoyeBa at 2007-7-21 9:33:56 > top of Java-index,Other Topics,Patterns & OO Design...
# 52

> I completely agree with this. I don't want my UI

> classes to know or care about where the set of child

> objects comes from. In fact, I don't want my UI

> classes to even know the concept of a database or

> files or whatever.

If you're doing this with Swing, it's no problem if the Listeners are part of the Controller and you inject them into the UI.

> I just don't like that you have to work with the

> assumption that a Hibernate Session is always open.

The service can open it, add it to session scope, and then have the SessionListener close the session when it's closed or timed out. No worries. The service and web tier are still handling everything. The UI does not know or care.

> I could use a DAO object to do a

> shapeDAO.getChildren(shape) (and make sure that the

> DAO object is associated with a Session), but

> Hibernate gives me the ability to simply call

> shape.getChildren(). However, if I don't have a

> Session open, Hibernate is going to throw a fit.

See above.

> I agree with this as well. I've never liked the idea

> of mirroring any part of my code tree.

But if you use DTOs and domain objects, that's exactly what you're doing.

%

duffymoa at 2007-7-21 9:33:56 > top of Java-index,Other Topics,Patterns & OO Design...
# 53

> The truth is, just because you hide the transaction

> and query inside of a runtime exception

Runtime exception?How are those involved with a runtime exception?

> and make the

> object look like an ordinary object, you still

> experience the delay of the database call as well as

> the risk of throwing database related exceptions

> during that call.

Well, that's the tradeoff. The alternative is eager loading and bringing the entire tree into memory. Nice, fast access then, but if the tree consists of 1000s of objects and the client won't actually need all of them you might not like that, either. You have to know something about your data and how it's used.

> Its a facade. But you can use

> Hibernate/JDO without hiding/ignoring exception

> throwing calls.

>

> When using DAO and DTO you know which objects can

> throw exceptions (DAO) and which can not (DTO).

So you do use both DTOs and domain objects? I thought in your previous response you said you don't