Help

Controls

PermLinkWikiLink

Built with Seam

You can find the full source code for this website in the Seam package in the directory /examples/wiki. It is licensed under the LGPL.

Forum: Weld Users Forum ListTopic List
31. May 2009, 21:02 CET | Link

In order to achieve Rich Domain Model it is often (very often in fact) necessary to inject objects managed by DI framework to entity beans. Current JSR-299 spec doesn't seem to support this in an easy way. You can of course access these objects programitcally but by doing this you lose DI benefits. Is there a way in JSR-299 to handle such a scenario? Maybe some Seam 3 extension is planned that uses Hibernate Interceptor, JSR-299 SPI or something else? What is WebBeans team view on solving this use case?

Regards, Rafał Hajdacki

59 Replies:
31. May 2009, 21:48 CET | Link

It should be possible to use the JSR-299 SPI's BeanManager.createInjectionTarget() and the resulting InjectionTarget.inject(...) method to inject dependencies into an entity bean via a @PostConstruct callback of the entity bean. I don't know if a Seam3 extension is planned along those lines, but if not, I plan on rolling my own and sharing it, because I too dislike anemic models.

 
Clint Popetz
http://42lines.net
Scalable Web Application Development
31. May 2009, 21:53 CET | Link

In my opinion, this is a horrible thing to do architecturally. Your domain model is the re-usable representation of your business. It should not be polluted by access to application-specific services.

Seriously, I'm a super-skeptic on architectural complexity, and I feel like I've spent my whole career advocating less layers, but even I don't advocate mixing your domain model, your infrastructural services, and your application-specific transaction logic into one big ball of dirty skanky nastiness.

 

Learn more about Weld...

31. May 2009, 22:04 CET | Link

Not to mention the fact that entities may be instantiated using new, even in a different physical tier of the application. An entity is not always a container-managed object. That's why it has the whole new-persistent-detached lifecycle model.

Do you really want to have to call Instance<Order>.get() to instantiate an Order?

 

Learn more about Weld...

31. May 2009, 23:09 CET | Link
In my opinion, this is a horrible thing to do architecturally. Your domain model is the re-usable representation of your business. It should not be polluted by access to application-specific services. Seriously, I'm a super-skeptic on architectural complexity, and I feel like I've spent my whole career advocating less layers, but even I don't advocate mixing your domain model, your infrastructural services, and your application-specific transaction logic into one big ball of dirty skanky nastiness.

Agree but what if one of my domain objects is not persistent but session scoped instead? For example session scoped Cart in online shop. I may be wrong but from high level perspective persistence can be considered as just another scope that is wider than @ApplicationScoped. We can come up with examples where nice OO design requires injection of session scoped domain object into persistent scoped domain object (similar to request scoped into session scoped injection). Gavin you wrote once that the power of Seam is that it doesn't enforce application structure on you. You just create classes the way it fits domain, Seam handles their lifecycle and you can use them directly from view (JSF) with very little or no plumbing code at all. I would extend that flexibility to persistent classes. What do you think?

BTW If you need some non-domain service layer then I agree that domain model shouldn't access it.

Not to mention the fact that entities may be instantiated using new

This would have to be solved by proper constructor I believe. In fact in nice OO design if object requires something it should be provided in constructor or method parameter. From this perspective no-argument constructor requirement in JPA spec can be considered a drawback but there are reason for that.

even in a different physical tier of the application. An entity is not always a container-managed object. That's why it has the whole new-persistent-detached lifecycle model.

Completely agree, if you need entities that should travel across physical tiers then you shouldn't access external objects from them. But the same is true for lazy initialized fields that were not initialized. Accessing them requires external persistence service which is similar to accessing external service object.

Do you really want to have to call Instance Order .get() to instantiate an Order?

Not really, I would like to use constructor injection in entities when they are created by EnitityManager and normal constructor instantiation in case of manual creation.

Regards, Rafał

31. May 2009, 23:28 CET | Link
Agree but what if one of my domain objects is not persistent but session scoped instead? For example session scoped Cart in online shop

Even if the Cart is persistent, you can easily put the Cart in the session scope using a producer method. You just would not be able to directly inject things into it (though you can inject into the producer method and pass the injected objects to the Cart constructor).

Or, if the point it is not persistent, what is the problem? You are trying to inject other things into it? Go ahead. Even if those other things

I may be wrong but from high level perspective persistence can be considered as just another scope that is wider than @ApplicationScoped.

No, things in the database are not uniquely identifiable by type/bindings. You need to look them up explicitly using a query API.

We can come up with examples where nice OO design requires injection of session scoped domain object into persistent scoped domain object (similar to request scoped into session scoped injection).

I'm certain that whatever usecase you come up with can be easily and more elegantly expressed using producer methods.

I'm also unclear on whether you are talking about an injection that happens once when you first instantiate the entity, and is thereafter stored persistently in the database as an association, or an injection that happens every time the entity is loaded. Two very different possible semantics.

You just create classes the way it fits domain, Seam handles their lifecycle and you can use them directly from view (JSF) with very little or no plumbing code at all. I would extend that flexibility to persistent classes. What do you think?

I don't think the analogy holds. There is an additional level of flexibility that is necessary in the case of entities: the flexibility to pass them around the system and use them in the absence of any container management. Secondly, in the case of entities, only very rarely do you encounter an entity that is singleton-ish. Normally, entities must be retrieved using queries, they can't just be injected without writing some code that specifies which one you're interested in. That code goes in the producer method.

This would have to be solved by proper constructor I believe. In fact in nice OO design if object requires something it should be provided in constructor or method parameter.

Right. And if I directly instantiate an object using its constructor, how does the container get an opportunity to inject dependencies of the object?

Not really, I would like to use constructor injection in entities when they are created by EnitityManager and normal constructor instantiation in case of manual creation.

Well, that would certainly be possible, and as Clint mentions, a portable extension could even provide that. But to me it seems like a very semantically weak kind of injection.

 

Learn more about Weld...

01. Jun 2009, 02:16 CET | Link
Gavin King wrote on May 31, 2009 21:53:
In my opinion, this is a horrible thing to do architecturally. Your domain model is the re-usable representation of your business. It should not be polluted by access to application-specific services. Seriously, I'm a super-skeptic on architectural complexity, and I feel like I've spent my whole career advocating less layers, but even I don't advocate mixing your domain model, your infrastructural services, and your application-specific transaction logic into one big ball of dirty skanky nastiness.

All of my comments below are only my $.02, with the implicit acknowledgement that you can create good and bad code regardless of your architectural approach, and hence my suggestions (and yours) can be misused by others, but that this misuse does not constitute a refutation of the worth of the approach in question. I also have a great deal of respect for your knowledge of architecture, in particular with regard to entities and dependency injection, Gavin.

If entities are containers of data, and only that, an argument against IoC in entities makes sense. However, when entities are true model objects, i.e. data and behavior representing a domain model, then they need to interact with other layers in order to accomplish the business logic they contain without resorting to skankiness. Interacting with other layers doesn't make you skanky. You do however need a clean way to do that. Injection is one such way.

The standard way to avoid adding IoC to model/entity classes is to leave them behaviorless (except for trivial validations that need no dependencies) and to shove all the logic into a DAO layer. That ends up creating horrible parallel graphs of Foo.java and FooManager.java, where the latter knows exactly how to hook a Foo to everything a Foo needs or that needs a Foo. Blech. A Foo at that point is essentially a C struct.

The repeated argument I've heard against adding dependencies to entities is simply that it's hard because sometimes the ORM creates entities and sometimes the application logic does, but that seems like an argument for creating a mechanism for handling that, rather than punting on making entities real objects.

I could go on, but it's better summarized here .

-Clint

 
Clint Popetz
http://42lines.net
Scalable Web Application Development
01. Jun 2009, 02:53 CET | Link

I really think you're setting up a false dichotomy here. I've heard this same argument before from other people. It is claimed that:

  1. it is very much more OO to put business behavior with data, and
  2. our entities hold most of the interesting data, so
  3. therefore, we need dependency injection in our entities.

But this argument is missing a couple of steps. First, you need to show that:

  • the kind of interesting business behavior that makes sense to package with the persistent data is the same logic that we usually want to implement in injectable beans, and
  • there is no other natural way to get injectable beans into an entity other than injecting them directly.

But I'm simply incredibly skeptical on both of these points. IMO, the kind of business logic that really belongs on your entities is the stuff that uses the entity, and other entities that are related to it by graph traversal, and not random other stuff that you get by injection. And if you really can find me some cases where you need to use the random other stuff in an operation that truly does belong on an entity, I don't see why you can't just pass that stuff as method parameters from something else that you can inject into.

 

Learn more about Weld...

01. Jun 2009, 03:09 CET | Link

And by the way, I'm not at all in favor of an anemic domain model, and so the only thing about that Fowler article that I don't agree with is the idea that EJB somehow encourages it. Indeed, the original EJB entity beans were conceived as rather heavyweight components with method-level transaction and security demarcation that were responsible for implementing rather non-trivial transaction processing! So it seems like Fowler has things exactly backward on that point: it is the POJO (meaningless term) model that does more to encourage the need for a service layer, since the service layer is absolutely needed for transaction and security management.

I think what happened here is the following chain of reasoning:

  • Anemic domain is Bad and
  • EJB is Bad,
  • therefore EJB forces you to use anemic domain.

Whatever, note that the Fowler article has nothing to say on the subject of injection, and so we don't know (or even especially care) what he would think about the topic we're discussing.

 

Learn more about Weld...

01. Jun 2009, 03:18 CET | Link

Actually, on the contrary, those folks who do want to inject into entities should perhaps take another look at entity beans in EJB2. That architecture does seem to be more like what you're looking for. Combine the EJB2 Entity Bean component model with a decent persistence mapping layer, and EJB 3.1-style annotations, and dependency injection via 299, and away you go... :-)

 

Learn more about Weld...

01. Jun 2009, 03:37 CET | Link
Gavin King wrote on Jun 01, 2009 02:53: But this argument is missing a couple of steps. First, you need to show that:
  • the kind of interesting business behavior that makes sense to package with the persistent data is the same logic that we usually want to implement in injectable beans, and

I guess you'll need to tell me what the same logic that we usually want to implement in injectable beans is, because I see no canonical definition of this type of logic. To me, for example, the following things are useful things to be injected:

  1. Things that might change based on deployment type
  2. Things that are optional, but which, if present, we want to make use of
  3. Things that our client code does not what to lookup manually
  4. Things that have a pluggable implementation, such that we wish to inject the interface but have no idea what the implementation will resemble or who will provide it.

I can think of a wealth of use cases for models to need each of those. Some examples:

  1. Almost all my entities want logging, but I need that logging to be implemented differently based on deployment type.
  2. My entities may want to provide an audit trail in @PreUpdate, but the audit interface is pluggable and may be a no-op, and the entity should not know about when or why that auditing mechanism changes, exists or doesn't, nor how to find it.
  3. My entity may, in response to a method invoked by application code, need to lookup references to newly-dependent entities. It would rather not embed the query in itself, because several other entity types also need to do something similar with this type of dependency, and the query should not be duplicated. So the query is abstracted to a DAO. But the client invoking the update method on my entity has no reason to know about the DAO, so it should not pass it as parameter to the entity, and the DAO has no useful state, so it should not be an entity to which my entity has a reference. The DAO is a dependency of some set of entities, and not of the business logic code that uses those entities.
  • there is no other natural way to get injectable beans into an entity other than injecting them directly.

Why on earth would that be required to make client code worthy of injection? In every case where you use injection there are other natural ways to get the injectable beans into the client code. We used these mechanisms for decades before injection arrived. Injection is simply cleaner, so we use it.

But I'm simply incredibly skeptical on both of these points. IMO, the kind of business logic that really belongs on your entities is the stuff that uses the entity, and other entities that are related to it by graph traversal, and not random other stuff that you get by injection.

I'm trying to understand what motivates this preferenced distinction between things I can reach by traversing my existing entity graph and things I can obtain by injection. Why is behavior I can find in my referenced entities ok to use, but behavior I can find via injection (or without injection, via static methods) random other stuff? From my entity's perspective, the things I can reach by traversing my set of references are injected. They're just injected by the ORM. And what you're really saying here is that only the ORM can inject things into an entity, because it knows what references an entity needs. But I told the ORM what things the entity needs, and I only told it things I needed to store in the database, because that's the role of the ORM. But there are other logical forms of dependencies that don't relate to object persistence, which are still dependencies my entity needs to do its job.

And if you really can find me some cases where you need to use the random other stuff in an operation that truly does belong on an entity, I don't see why you can't just pass that stuff as method parameters from something else that you can inject into.

I can say the same of any object that uses injection. That's a straw man.

As an aside, did you never write:

@Logger Log log;

in an entity (post-Seam), and absolutely love it? Why are we stopping there?

 
Clint Popetz
http://42lines.net
Scalable Web Application Development
01. Jun 2009, 03:48 CET | Link

The point is that I have a good reason for thinking that entities should not depend upon things that they can only obtain from the container: the reason is that we often want to be able to serialize them around the system and use them in execution contexts where there is no container (or a logically different container).

 

Learn more about Weld...

01. Jun 2009, 06:44 CET | Link

Active record is the pattern that applies to the anemic domain model situation (there is actually some coverage of this in the SiA book when DAllen is covering the Seam Application Framework). I don't have experience with RoR or Active Record, but...

Active Record attempts to provide a coherent wrapper as a solution for the inconvenience that is object-relational mapping. The prime directive for this mapping has been to minimize the amount of code needed to build a real-world domain model. This is made possible by relying on a number of conventions that make it easy for Active Record to infer complex relations and structures from a minimal amount of explicit direction.

Convention over Configuration:

- No XML-files! - Lots of reflection and run-time extension - Magic is not inherently a bad word

Admit the Database:

- Lets you drop down to SQL for odd cases and performance - Doesn‘t attempt to duplicate or replace data definitions

source: http://ar.rubyonrails.org

I'm not sure if I'd refer to ORM as inconvenient, at least we have HibernateTools (hbm2java specifically) and 1st and 2nd level caches; if you have that mind-set then use OODBMS like db4o, InterSystems Cache, etc.

I really think that application tx (aka atomic conversation) using SMPC and Hibernate MANUAL flushMode extension is a very useful tool in Seam apps.

Transaction support in ActiveRecord::Transactions::ClassMethods module is weak at best (e.g. no distributed tx support).

But if you really dislike anemic models, then use RoR or similar. Or find a way to integrate that into your JEE apps. Hey, at least the DTO pattern is now an anti-pattern in EJB3...

My concern is not so much the anemic domain problem as much as when will OODBMS and JEE integration become a JSR so we don't need to use ORM anymore. RDBMS has been around since the 70's, no? I know a lot of corporations are using RDBMS but finally they will be phased out with new technology like OODBMS. Ted Neward has blogged about the OODBMS topic a lot.

 

required reading: Scala and more Scala... www.artima.com

01. Jun 2009, 07:20 CET | Link
Gavin King wrote on Jun 01, 2009 03:48:
we often want to be able to serialize them around the system and use them in execution contexts where there is no container (or a logically different container).

Is that the common case? I've never needed to do that. Maybe that's just me.

And even if it is the common case, entity injection availability doesn't require entities to necessarily use it; the author of an entity will know whether the it will need to be serialized to a different (container-less) execution context, and can code accordingly.

01. Jun 2009, 07:59 CET | Link

so it sounds like you guys are saying why can't DI be available/optional in entity classes? if it's available and you don't use it, then GKing's concerns are irrelevant in those cases (e.g. unit testing). JavaBean Seam components can have injections and implement java.io.Serializable, no? So if they can, why can't entity classes as well?

PEAA by Fowler does not cover DI at all.

I looked at the Active Record pattern in that book and the examples showed static CRUD methods in the entity class. Also business logic methods are in the entity class.

Their primary problem is that they would work well only if the Active Record objects correspond directly to the database tables: an isomorphic schema.

If your business logic is complex (relations, inheritance, etc), it's better to use Data Mapper.

I prefer not to have business logic in my entity classes.

But I guess the argument is, if for some reason we need to add business logic to entity class, then we may need injections?

But why do you need to have the biz logic in the entity class in the first place? What's wrong with separation of concerns and doing the biz logic in a JavaBean or EJB?

Or what about allowing DI in entity classes only via XML, not annotations?

How much do you really gain by adding biz logic methods to entity class? Perhaps you won't have to repeat code in multiple business components (DRY principle) if it's already a method in the entity class...

Overall, I'm siding with GKing on this one until somebody provides a concrete example of why/when you'd need DI in entity classes and what the gain/advantage is...

 

required reading: Scala and more Scala... www.artima.com

01. Jun 2009, 09:11 CET | Link
Gavin King wrote on Jun 01, 2009 03:48:
The point is that I have a good reason for thinking that entities should not depend upon things that they can only obtain from the container: the reason is that we often want to be able to serialize them around the system and use them in execution contexts where there is no container (or a logically different container).

But in most cases they do depend on things that can be obtained only from the container: lazy initialized fields. We can think of external services similar to them. It is application specific, if you need transportable entities then don't use dependencies that may cause problems.

01. Jun 2009, 10:44 CET | Link
Even if the Cart is persistent, you can easily put the Cart in the session scope using a producer method. You just would not be able to directly inject things into it (though you can inject into the producer method and pass the injected objects to the Cart constructor).

I want to handle use cases where request/seesion/application scoped object is accessed by entity. Great example provided by Clint is Logger.

I may be wrong but from high level perspective persistence can be considered as just another scope that is wider than @ApplicationScoped. No, things in the database are not uniquely identifiable by type/bindings. You need to look them up explicitly using a query API.

Is that really a requirement for DI / scoping? It is just current state of things in JSR-299. We can come up with injection point that for example takes entity ID as parameter and injects Entity instance. Or even query in order to access collection of entities. This could work similar to Any in JSR-299.

I'm also unclear on whether you are talking about an injection that happens once when you first instantiate the entity, and is thereafter stored persistently in the database as an association, or an injection that happens every time the entity is loaded. Two very different possible semantics.

I am talking about second case here. Don't want to store it in database.

I don't think the analogy holds. There is an additional level of flexibility that is necessary in the case of entities: the flexibility to pass them around the system and use them in the absence of any container management.

This flexibility is not always required. This is application specific I think. If you want transportable objects you just don't expose not initialized persistent fields and external objects/services.

Secondly, in the case of entities, only very rarely do you encounter an entity that is singleton-ish. Normally, entities must be retrieved using queries, they can't just be injected without writing some code that specifies which one you're interested in. That code goes in the producer method.

Does something have to singleton-ish in order to support injection? Well I just see EntityManger as just another context that I can access programmatically. As mentioned above we can also use query or entity id for injection point to support enity injection into other objects.

This would have to be solved by proper constructor I believe. In fact in nice OO design if object requires something it should be provided in constructor or method parameter. Right. And if I directly instantiate an object using its constructor, how does the container get an opportunity to inject dependencies of the object?

It doesn't. If you create objects manually you have to do it on you own.

Not really, I would like to use constructor injection in entities when they are created by EnitityManager and normal constructor instantiation in case of manual creation. Well, that would certainly be possible, and as Clint mentions, a portable extension could even provide that. But to me it seems like a very semantically weak kind of injection.

Why is it semantically weak?

01. Jun 2009, 12:58 CET | Link
Overall, I'm siding with GKing on this one until somebody provides a concrete example of why/when you'd need DI in entity classes and what the gain/advantage is...

How about Logger injection into entities?

01. Jun 2009, 14:28 CET | Link
Gavin King wrote on Jun 01, 2009 03:48:
The point is that I have a good reason for thinking that entities should not depend upon things that they can only obtain from the container: the reason is that we often want to be able to serialize them around the system and use them in execution contexts where there is no container (or a logically different container).

That's a perfectly legitimate requirement, and a good reason to be very careful about creating dependencies in the model layer if you have it. I've never had that requirement, nor do I see it as a natural endpoint for the types of problems we solve.

I think our difference on this issue may be due to our definition of entity. To me, the only connotation inferred from the @Entity annotation is persistence. By designating an class an entity I am agreeing to obey the rules of JPA in order to make use of a JPA provider to map my object to a table. If (for example) one uses an entity in RMI situations, then that imposes additional requirements, but that's orthogonal to the question of what's good or bad for entities. That's why I accept the argument that the entity lifecycle complicates injection, because that argument is based on a characteristic that entities share by definition.

 
Clint Popetz
http://42lines.net
Scalable Web Application Development
01. Jun 2009, 15:55 CET | Link
Secondly, in the case of entities, only very rarely do you encounter an entity that is singleton-ish. Normally, entities must be retrieved using queries, they can't just be injected without writing some code that specifies which one you're interested in. That code goes in the producer method.
Does something have to singleton-ish in order to support injection? Well I just see EntityManger as just another context that I can access programmatically. As mentioned above we can also use query or entity id for injection point to support enity injection into other objects.

Gavin, but WebBeans's Logger is also not singleton-ish and yet you consider it a good candidate for injection. There are many instances of it from which only one is selected and injected using injection point metadata as id source. Entities can be handled in a similar way. The one thing that is different as Clint mentioned is more complicated life cycle of entities. But really is there anything in it that is a deal breaker for supporting injection?

01. Jun 2009, 16:01 CET | Link

I want to clarify that I am not advocating adding injection of entities to JCDI. That level of modification of the existing specification at this point in its lifecycle wouldn't be advisable or even feasible, and the semantics of entity injection needs a lot more thought in any case.

I am however advocating the investigation of a webbeans extension, either in Seam3 or otherwise, that would support this.

 
Clint Popetz
http://42lines.net
Scalable Web Application Development
01. Jun 2009, 16:21 CET | Link
I want to clarify that I am not advocating adding injection of entities to JCDI. That level of modification of the existing specification at this point in its lifecycle wouldn't be advisable or even feasible, and the semantics of entity injection needs a lot more thought in any case.

I am also not advocating it. In fact I am strongly against for doing it now. I am only arguing that considering persistence as just another context that can be handled by DI is feasible in general. But of course there are probably lots of issues hidden in JPA-JCDI integration in order to achieve it in an elegant way.

My point of mentioning this idea is to support general perspective that it is sensible to think about DI-managed and EM-managed objects as just domain objects that can access each other and that reasons for not doing so comes from other requirements/use cases that are not related to standard domain logic design.

I am however advocating the investigation of a webbeans extension, either in Seam3 or otherwise, that would support this.

Agree. This was my initial point starting this thread.

01. Jun 2009, 18:24 CET | Link
Rafal Hajdacki wrote on Jun 01, 2009 12:58:
Overall, I'm siding with GKing on this one until somebody provides a concrete example of why/when you'd need DI in entity classes and what the gain/advantage is...
How about Logger injection into entities?

Seriously, if logging is the best usecase you can come up with...

 

Learn more about Weld...

01. Jun 2009, 18:34 CET | Link
Rafal Hajdacki wrote on Jun 01, 2009 10:44:
Even if the Cart is persistent, you can easily put the Cart in the session scope using a producer method. You just would not be able to directly inject things into it (though you can inject into the producer method and pass the injected objects to the Cart constructor).
I want to handle use cases where request/seesion/application scoped object is accessed by entity. Great example provided by Clint is Logger.

seems like a kinda lame example to me :-)

I may be wrong but from high level perspective persistence can be considered as just another scope that is wider than @ApplicationScoped. No, things in the database are not uniquely identifiable by type/bindings. You need to look them up explicitly using a query API.
Is that really a requirement for DI / scoping? It is just current state of things in JSR-299. We can come up with injection point that for example takes entity ID as parameter and injects Entity instance. Or even query in order to access collection of entities. This could work similar to Any in JSR-299.

This is a case of injecting entities into other things, not a case of injecting other things into entities. This can be handled today with magical things like producer methods and InjectionPoint.

This would have to be solved by proper constructor I believe. In fact in nice OO design if object requires something it should be provided in constructor or method parameter. Right. And if I directly instantiate an object using its constructor, how does the container get an opportunity to inject dependencies of the object?
It doesn't. If you create objects manually you have to do it on you own.
Not really, I would like to use constructor injection in entities when they are created by EnitityManager and normal constructor instantiation in case of manual creation. Well, that would certainly be possible, and as Clint mentions, a portable extension could even provide that. But to me it seems like a very semantically weak kind of injection.
Why is it semantically weak?

Because its a field that is sometimes injected and so sometimes has the semantics specified by the annotations declared at the injection point.

 

Learn more about Weld...

01. Jun 2009, 20:39 CET | Link
Gavin King wrote on Jun 01, 2009 18:24:
Rafal Hajdacki wrote on Jun 01, 2009 12:58:
Overall, I'm siding with GKing on this one until somebody provides a concrete example of why/when you'd need DI in entity classes and what the gain/advantage is...
How about Logger injection into entities?
Seriously, if logging is the best usecase you can come up with...

I don't think logging by itself (one use case) qualifies as a solid case for allowing DI in entity classes. Although it may be more convenient to have access to DI in an entity class, you can still use JNDI lookup, no?

It really comes down to whether or not business logic belongs in an entity class. If it does (in some cases), then perhaps DI should be under consideration.

I mean do you really need to do some calculation, for example, in an entity class? Why can't that logic happen in a DAO, for example?

The only advantage I see with having the biz logic embedded in an entity class (as a public method), is you don't have to factor that method into an auxiliary helper class that is injected into a SFSB or DAO class everytime it is needed. So essentially it would cut down on coding. Especially in the case where you have an interface (e.g., Vehicle) which is implemented by Car, Truck, and SUV entity classes. That biz logic (calculation, etc.) may be common to all the entities and may belong in the interface or perhaps an abstract class with implementation.

So let's say you have a valid case and need to embed the public calculation method in the entity class, do we need access to EntityManager interface directly at this point for CRUD ops? I hope not. I think it's better to maintain separation of concerns, but at the same time minimize layering if possible.

This is one thing I agree on with GKing and one main reason I liked Seam from the beginning (no forced layering and patterns like Struts/EJB2.x!)

 

required reading: Scala and more Scala... www.artima.com

01. Jun 2009, 20:51 CET | Link
Seriously, if logging is the best usecase you can come up with...

Seriously, if you don't consider logging a valid use case ... ;-) Why you have added injected logger to Seam and WebBeans extensions then? And who said it is the best use case? How about application scoped FileManager that abstracts access to files which we don't want to store in blobs? How about use cases provided by Clint?

01. Jun 2009, 22:08 CET | Link
I want to handle use cases where request/seesion/application scoped object is accessed by entity. Great example provided by Clint is Logger.
seems like a kinda lame example to me :-)

That's for sure the ultimate argument Gavin. :-) Agree that logging seems trivial but it is still very frequent and valid use case. Let's make it less trivial then. How about audit logging that is common in financial/payment applications. You better make sure every financial operation is reported. And database is not always target storage for such audit traces. So injected AuditLogger would be very handy in entity beans. If this is lame use case then tell it to our customers. I would love to see their faces. ;-)

This is a case of injecting entities into other things, not a case of injecting other things into entities. This can be handled today with magical things like producer methods and InjectionPoint.

Please keep context of the discussion. I have provided ideas regarding injecting of entities into other things as example that the analogy of persistence to other context holds. And that injecting other things into entities is similar to injecting request scoped objects into session scoped objects. As arguments against that you first mentioned that things in the database are not uniquely identifiable by type/bindings which I showed is not requirement for DI. Second you argued that entities are not singleton-ish which I refuted by mentioning Logger which is also not really singleton-ish and yet fits DI (heck, you seem to have introduced InjectionPoint mostly to support such non singleton-ish cases). Third argument was that entities need to be transportable across container boundaries. But as me and Clint answered this requirement is really orthogonal to DI and also is not present in many applications.

Any other arguments against that analogy?

As for magical things provided by JSR-299, I am well aware of them as I follow spec changes and your blog since the beginning. As I mentioned in previous comment I don't argue here for adding support for alternative ways of entity injection into other things. This was just for the sake of argument.

Why is it semantically weak?
Because its a field that is sometimes injected and so sometimes has the semantics specified by the annotations declared at the ijection point.

Agree, such a injection is really semantically weak. You have to use Instance<Order>.get() to avoid that. But really when you create entity manually you are on your own to provide dependencies.

01. Jun 2009, 22:29 CET | Link
Gavin King wrote on Jun 01, 2009 03:09:
Whatever, note that the Fowler article has nothing to say on the subject of injection, and so we don't know (or even especially care) what he would think about the topic we're discussing.

And Fowler most likely doesn't care about Seam or Web Beans as is evidenced by the fact that his blog entries are dated back to 2003, pre-EJB3, which is kinda lame. Nevertheless...

I don't know why this anti-pattern is so common. I suspect it's due to many people who haven't really worked with a proper domain model, particularly if they come from a data background. Some technologies encourage it; such as J2EE's Entity Beans which is one of the reasons I prefer POJO domain models. In general, the more behavior you find in the services, the more likely you are to be robbing yourself of the benefits of a domain model. If all your logic is in services, you've robbed yourself blind.

Why does he say you're robbing yourself?

The logic that should be in a domain object is domain logic - validations, calculations, business rules - whatever you like to call it.

Validations is (mostly) solved by Hibernate validators. How often do we need calculations in CRUD apps in the domain model? And don't business rules belong in the business logic tier?

source: http://martinfowler.com/bliki/AnemicDomainModel.html

 

required reading: Scala and more Scala... www.artima.com

01. Jun 2009, 22:38 CET | Link
Rafal Hajdacki wrote on Jun 01, 2009 22:08:
That's for sure the ultimate argument Gavin. :-) Agree that logging seems trivial but it is still very frequent and valid use case. Let's make it less trivial then. How about audit logging that is common in financial/payment applications. You better make sure every financial operation is reported. And database is not always target storage for such audit traces. So injected AuditLogger would be very handy in entity beans. If this is lame use case then tell it to our customers. I would love to see their faces. ;-)

CBauer presented an auditing solution IIRC in Bauer/King book. Also........

The Envers project aims to enable easy auditing/versioning of persistent classes. All that you have to do is annotate your persistent class or some of its properties, that you want to audit, with @Audited. For each audited entity, a table will be created, which will hold the history of changes made to the entity. You can then retrieve and query historical data without much effort.

source: http://www.jboss.org/envers/

So what is it about one of these two solutions that is insufficient for your logging/auditing use case?

Do you need one audit table for all entities or one audit table for each entity?

 

required reading: Scala and more Scala... www.artima.com

01. Jun 2009, 22:45 CET | Link
Arbi Sookazian wrote on Jun 01, 2009 20:39:
I don't think logging by itself (one use case) qualifies as a solid case for allowing DI in entity classes.

Agree. But sure it would be nice to have it. Don't you think? There are other cases. See my and Clint's previous entries.

Although it may be more convenient to have access to DI in an entity class, you can still use JNDI lookup, no?

Sure I can. But we have DI to handle this better. Right? Why don't you use JNDI lookup in services?

It really comes down to whether or not business logic belongs in an entity class. If it does (in some cases), then perhaps DI should be under consideration.

Even Gavin agrees that that it belongs in some cases. I would argue that it belongs in additional cases. OO is all about it, right?

I mean do you really need to do some calculation, for example, in an entity class? Why can't that logic happen in a DAO, for example?

Sure it can. But for OO-geeks it seems nice to have method that operates on data located in the same object as data. :-)

The only advantage I see with having the biz logic embedded in an entity class (as a public method), is you don't have to factor that method into an auxiliary helper class that is injected into a SFSB or DAO class everytime it is needed.

That's huge advantage. There are other benefits of OO design though. The are also drawbacks.

So let's say you have a valid case and need to embed the public calculation method in the entity class, do we need access to EntityManager interface directly at this point for CRUD ops? I hope not.

In most cases you just access local persistent fields like collections to do that. So no need to access EntityManager.

I think it's better to maintain separation of concerns, but at the same time minimize layering if possible.

What are these concerns that should be separated?

This is one thing I agree on with GKing and one main reason I liked Seam from the beginning (no forced layering and patterns like Struts/EJB2.x!)

Me too. But from my point of view Gavin is insisting on this last artificial layer. :-)

01. Jun 2009, 22:58 CET | Link
Rafal Hajdacki wrote on Jun 01, 2009 22:45:
This is one thing I agree on with GKing and one main reason I liked Seam from the beginning (no forced layering and patterns like Struts/EJB2.x!)
Me too. But from my point of view Gavin is insisting on this last artificial layer. :-)

What do you mean exactly by last artificial layer? Does that comment refer to DAO layer and/or entity class?

GKing is most likely not the only one in the EG's insisting on this IMO.

Most likely there is some agreement from Linda DeMichiel and Mike Keith as well (I'm just guessing so shoot me if I'm wrong :).

It sounds like your intent here is to somehow collapse this last artificial layer into the entity class and therefore take the JPA entity class back to what it was in EJB2.x as an entity bean which was more similar to Active Record pattern.

If you add injection and domain logic to your entity class, will it still be easily tested outside the EJB container? This was one of the main problems with EJB2.x and prior...

 

required reading: Scala and more Scala... www.artima.com

01. Jun 2009, 23:00 CET | Link
Arbi Sookazian wrote on Jun 01, 2009 22:38:
CBauer presented an auditing solution IIRC in Bauer/King book. Also........ The Envers project aims to enable easy auditing/versioning of persistent classes. All that you have to do is annotate your persistent class or some of its properties, that you want to audit, with @Audited. For each audited entity, a table will be created, which will hold the history of changes made to the entity. You can then retrieve and query historical data without much effort. source: http://www.jboss.org/envers/ So what is it about one of these two solutions that is insufficient for your logging/auditing use case? Do you need one audit table for all entities or one audit table for each entity?

This approach is perfectly fine for simple auditing that just audits database operations. Unfortunately auditing in many cases is more complex then that. Imagine that auditing operations are use case specific and take different number of arguments for each use case. These arguments are not always related to changed entity and can't be provide in a declarative way. Add that it has to be plugabble to support different outputs. How would you handle such a use case?

01. Jun 2009, 23:18 CET | Link
This is one thing I agree on with GKing and one main reason I liked Seam from the beginning (no forced layering and patterns like Struts/EJB2.x!)
Me too. But from my point of view Gavin is insisting on this last artificial layer. :-)
What do you mean exactly by last artificial layer? Does that comment refer to DAO layer and/or entity class?

This last layer are entities that shouldn't access other objects. For me they are just objects that have wider scope than application scoped beans and it is up to domain logic design to decided what should access what.

GKing is most likely not the only one in the EG's insisting on this IMO.

I am sure he is not the only one. From my experience I would even say that proponents of injection into entities are the minority. But I may be wrong. At least most applications I worked with doesn't use this kind of injection. :-)

Most likely there is some agreement from Linda DeMichiel and Mike Keith as well (I'm just guessing so shoot me if I'm wrong :).

I would really like to know all the arguments against this approach. I am not here to convince others to my view. I want to validate whether my view is valid. I haven't heard convincing argument yet though. Or maybe I am missing something.

It sounds like your intent here is to somehow collapse this last artificial layer into the entity class and therefore take the JPA entity class back to what it was in EJB2.x as an entity bean which was more similar to Active Record pattern.

No, I just want to treat entity as a real object that can access other objects using DI. :-)

If you add injection and domain logic to your entity class, will it still be easily tested outside the EJB container? This was one of the main problems with EJB2.x and prior...

Are your service objects testable outside EJB container? From my perspective entities can depend on objects located in other context. DI should provide these dependencies. Entity shouldn't know how they are provided. In test you can provide them manually or use DI framework for that. Similar to service objects.

02. Jun 2009, 00:22 CET | Link
Rafal Hajdacki wrote on Jun 01, 2009 23:00:
Arbi Sookazian wrote on Jun 01, 2009 22:38:
CBauer presented an auditing solution IIRC in Bauer/King book. Also........ The Envers project aims to enable easy auditing/versioning of persistent classes. All that you have to do is annotate your persistent class or some of its properties, that you want to audit, with @Audited. For each audited entity, a table will be created, which will hold the history of changes made to the entity. You can then retrieve and query historical data without much effort. source: http://www.jboss.org/envers/ So what is it about one of these two solutions that is insufficient for your logging/auditing use case? Do you need one audit table for all entities or one audit table for each entity?
This approach is perfectly fine for simple auditing that just audits database operations. Unfortunately auditing in many cases is more complex then that. Imagine that auditing operations are use case specific and take different number of arguments for each use case. These arguments are not always related to changed entity and can't be provide in a declarative way. Add that it has to be plugabble to support different outputs. How would you handle such a use case?

Well unfortunatley, that's most likely not a typical use case. Which reminds me of my attempt a few months back (and GKing is well aware of this) to convince the JPA 2.0 EG regarding MANUAL flushMode as follows:

Regarding section 3.6.2 of JPA 2.0 EDR spec, the proposal is to add a MANUAL value and associated semantics in related parts of the spec to FlushModeType enum which currently only supports COMMIT and AUTO (since JPA 1.0)

Mike Keith vehemently opposed. In fact, JPA 2.0 AFAIK does not support stored procs (Hibernate does).

My point is this: these outlying spec requests and/or use cases may not be seriously considered.

The JCP is inundated with technical and political problems (the latter is unfortunate) and what is even more unfortunate is that you should be able to discuss this topic and other JSR/JCP related topics freely on discussion boards/forums sponsored by Sun but that's not currently available AFAIK.

 

required reading: Scala and more Scala... www.artima.com

02. Jun 2009, 00:27 CET | Link
Arbi Sookazian wrote on Jun 01, 2009 06:44:
But if you really dislike anemic models, then use RoR or similar.

AFAIK RoR is as anemic (or more) than @Entities, if you really do not like anemic models, use Apple EOF or Cayenne both of them help you create an architecture where the business logic is inside your entities, an approach completly different from the ActiveRecord one.

Or find a way to integrate that into your JEE apps. Hey, at least the DTO pattern is now an anti-pattern in EJB3...

Is it? We still need them.

My concern is not so much the anemic domain problem as much as when will OODBMS and JEE integration become a JSR so we don't need to use ORM anymore. RDBMS has been around since the 70's, no? I know a lot of corporations are using RDBMS but finally they will be phased out with new technology like OODBMS. Ted Neward has blogged about the OODBMS topic a lot.

Many have tried that approach, and it has failed, specially performance wise, I do not think that the future are OODBMS, I think the future, if we are lucky, will be when we recognize that current RDBMS are not really relational, and what we dislike about them is not that they have relational limitations, what we dislike is that SQL is full of flaws, and we really need is a TRDBMs database with a truly relational language.

 

Please don't forget to rate!

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. - Antoine de Saint Exupéry

Please visit my blog

02. Jun 2009, 00:41 CET | Link
Arbi Sookazian wrote on Jun 01, 2009 07:59:
I prefer not to have business logic in my entity classes.

Then you like to create Anemic Domain Models

But I guess the argument is, if for some reason we need to add business logic to entity class, then we may need injections?

Well, in some architectures/frameworks, the entity class is known as business object, so, it makes sense that the business objects has the business logic inside it.

But why do you need to have the biz logic in the entity class in the first place? What's wrong with separation of concerns and doing the biz logic in a JavaBean or EJB?

There is nothing wrong.. if you like Anemic Domain Models

Or what about allowing DI in entity classes only via XML, not annotations? How much do you really gain by adding biz logic methods to entity class? Perhaps you won't have to repeat code in multiple business components (DRY principle) if it's already a method in the entity class...

Think for example that you want all the purchases for a client, with an ORM, you tipically get them using client.getPurchases(); Now let say you want all the purchases in year 2000.... Does it make sense to be able to write: client.getPurchasesFromYear(2000); But you can not do that, because there is no way to inject the entityManager (or the purchases DAO) in to the client entity. So you end up with 2 very different ways of querying stuff, and in my experience you end up needing to query for the purchases of a client using may different filters (by year, between dates, by total cost, etc, etc). If you can ot write those queries as methods for the customer... then you will have to do that on a DAO (and if you use DAOs, then you are creating an Anemic Domain Model)

Overall, I'm siding with GKing on this one until somebody provides a concrete example of why/when you'd need DI in entity classes and what the gain/advantage is...

Take a look at this presentation Make Roles Explicit. Now think how convenient is to have IoC for the time when you need to change the implementation of a particular role to new, more efficient one, or to a new persistence service. That is why it would be really nice to have IoC on entities (it is not that it can not be done without it, we can do with plain JDBC anything that can be done with JPA, it is that it would be a lot more convenient)

 

Please don't forget to rate!

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. - Antoine de Saint Exupéry

Please visit my blog

02. Jun 2009, 08:32 CET | Link

There wouldn't any difficulty with wrapping the JPA EntityManager with your own that did injection. Actually sounds rather trivial to do with the SPI classes.

I think to win people over you should show some examples of this in practice.

02. Jun 2009, 15:56 CET | Link
Arbi Sookazian wrote on Jun 02, 2009 00:22:
Well unfortunatley, that's most likely not a typical use case.

Well, what is typical and what is not is very relative...and since Envers is pretty new I guess that Rafal approach is more common... specially since AFAIK Envers is Hibernate specific...

Which reminds me of my attempt a few months back (and GKing is well aware of this) to convince the JPA 2.0 EG regarding MANUAL flushMode as follows: Regarding section 3.6.2 of JPA 2.0 EDR spec, the proposal is to add a MANUAL value and associated semantics in related parts of the spec to FlushModeType enum which currently only supports COMMIT and AUTO (since JPA 1.0) Mike Keith vehemently opposed. In fact, JPA 2.0 AFAIK does not support stored procs (Hibernate does).

I do not see the relationship between MANUAL flushMode , and Injection into entity beans, but I do have a hard time understanding why MANUAL is needed... I also tried to convince the EclipseLink team to help me find a way to emulate FlushMode.MANUAL, to migrate to EclipseLink and avoid this hibernate bug, and take advantage of EclipseLink nested units of work (that are IMO a good match for nested conversations), but I end up convinced there was no real reason to have FlushMode.MANUAL (it would be nice to have a code example explaining what is so good about FlushMode.MANUAL, because I really do not get it) .

My point is this: these outlying spec requests and/or use cases may not be seriously considered. The JCP is inundated with technical and political problems (the latter is unfortunate) and what is even more unfortunate is that you should be able to discuss this topic and other JSR/JCP related topics freely on discussion boards/forums sponsored by Sun but that's not currently available AFAIK.

Yes, I agree 100% with you that we should have discussion boards/forums sponsored by Sun to discuss this kind of things, (maybe nabble will help with that? or maybe now that Sun is part of Oracle there will be a section for that in oracle forums?). I hope there be a way to ask Oracle for that.

 

Please don't forget to rate!

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. - Antoine de Saint Exupéry

Please visit my blog

02. Jun 2009, 17:38 CET | Link
Elias Ross wrote on Jun 02, 2009 08:32:
There wouldn't any difficulty with wrapping the JPA EntityManager with your own that did injection. Actually sounds rather trivial to do with the SPI classes. I think to win people over you should show some examples of this in practice.

Examples... like this presentation? ;)

 

Please don't forget to rate!

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. - Antoine de Saint Exupéry

Please visit my blog

02. Jun 2009, 18:38 CET | Link
it would be nice to have a code example explaining what is so good about FlushMode.MANUAL, because I really do not get it
@Stateful @ConversationScoped
public class OrderConversation {

    @PersistenceContext(type=EXTENDED) EntityManager em;
    @Current Conversation conversation;
    private Order order;

    public Order getOrder() { return order; }

    public void load(int id) {
        conversation.begin();
        em.setFlushMode(MANUAL);
        order = em.get(User.class, id);
    }

    public void addLineItemByAjax(Product product, int quantity) {
        order.addLineItem( new LineItem(product, quantity) );
    }

    public void removeLineItemByAjax(LineItem li) {
        order.removeLineItem(li);
    }

    public void commitAllChanges() {
        em.flush();
        conversation.end();
    }

}

All changes are written to the database atomically at the end of the conversation. What's not to get?

 

Learn more about Weld...

02. Jun 2009, 19:28 CET | Link

And Seam could be adapted to achieve the same affect with em.setFlushMode(COMMIT); or not?

em.setFlushMode(MANUAL); delays flushing until em.flush();, em.setFlushMode(COMMIT) delays flushing until em.getTransaction().commit(); what is the big difference?.

 

Please don't forget to rate!

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. - Antoine de Saint Exupéry

Please visit my blog

02. Jun 2009, 19:39 CET | Link
Gavin King wrote on Jun 02, 2009 18:38:
it would be nice to have a code example explaining what is so good about FlushMode.MANUAL, because I really do not get it
@Stateful @ConversationScoped
public class OrderConversation {

    @PersistenceContext(type=EXTENDED) EntityManager em;
    @Current Conversation conversation;
    private Order order;

    public Order getOrder() { return order; }

    public void load(int id) {
        conversation.begin();
        em.setFlushMode(MANUAL);
        order = em.get(User.class, id);
    }

    public void addLineItemByAjax(Product product, int quantity) {
        order.addLineItem( new LineItem(product, quantity) );
    }

    public void removeLineItemByAjax(LineItem li) {
        order.removeLineItem(li);
    }

    public void commitAllChanges() {
        em.flush();
        conversation.end();
    }

}
All changes are written to the database atomically at the end of the conversation. What's not to get?

GKing's above statement is true if you are using sequences (e.g. Oracle). If you are using IDENTITY to generate the next PK value, then it's possible that there will be premature commits/tx's to the db prior the em.flush() at the end of the LRC.

I never got a technical explanation (note the closedness of the JCP in this respect) from Mike Keith regarding why he was opposed to MANUAL flush, most likely a political issue, who knows.

SiA:

If the entity identifier is generated during an insertion (i.e., auto-increment column), then even with manual flushing, a flush occurs after a call to persist(). This is necessary since each managed entity in the persistence context must be assigned an identifier. To avoid the flush, you need to set the id-generation strategy to sequence (not identity).

In any event, this technique (atomic conversations) using SMPC (in Seam) and Hibernate MANUAL flush takes advantage of the 1st level cache of JPA/Hibernate. This means that your app will be less chatty that other apps that use stored procs, for example.

If you think about this scenario, you don't even have to write a single JPAQL/HQL API statement to persist the data:

3 pages in a LRC (wizard). all pages, the user updates the form data and submits. the final submit button on the 3rd page flushes the EntityManager and ends the LRC. You don't need to write a single line of JPA code b/c at when the tx commits, the PersistenceContext is synchronized with the db tables (this is called write-behind).

SiA:

Maintain a persistence context —The persistence context is an in-memory cache of all entity instances that have been loaded into memory by this manager. It is the key to optimizing performance and enabling write-behind database operations (queued SQL statements). It's often referred to as the first-level cache. The terms persistence context and persistence manager are often used interchangeably.
 

required reading: Scala and more Scala... www.artima.com

02. Jun 2009, 19:40 CET | Link

Because a JTA transaction corresponds to a database-level transaction. You are suggesting holding a database session and transaction open across user-think time? What happens if there is a limit to the number of available connections (this is how relational databases are priced). What happens if the user goes away - the connection/transaction gets cleaned up by a timeout?

This is something that has always been discouraged in applications that need to scale to many users. Now, it's not clear to me that this isn't just a problem with how today's JDBC drivers / relational databases are implemented, but I've not yet heard anyone saying that this advice is now out of date and that it is now perfectly fine to hold on to connections/transactions.

Now, could you, conceptually, introduce come kind of optimistic transaction abstraction in the JTA layer? Yes, it is probably conceptually possible, but I think there would be a huge resistance to that, since it would require a major rethink to how statement-oriented APIs like JDBC work.

 

Learn more about Weld...

02. Jun 2009, 19:45 CET | Link
true if you are using sequences (e.g. Oracle). If you are using IDENTITY to generate the next PK value, then it's possible that there will be premature commits/tx's to the db prior the em.flush() at the end of the LRC.

Arguably this is just a limitation in how Hibernate currently implements this feature. There's nothing conceptually broken about delaying id generation until the explicit flush occurs. Hibernate just doesn't know how to do this today.

 

Learn more about Weld...

02. Jun 2009, 20:12 CET | Link
Gavin King wrote on Jun 02, 2009 19:45:
true if you are using sequences (e.g. Oracle). If you are using IDENTITY to generate the next PK value, then it's possible that there will be premature commits/tx's to the db prior the em.flush() at the end of the LRC. Arguably this is just a limitation in how Hibernate currently implements this feature. There's nothing conceptually broken about delaying id generation until the explicit flush occurs. Hibernate just doesn't know how to do this today.

I was about to write that this limitation was not existent on EclipseLink, but you beat me by writing that this is just a limitation in how Hibernate currently implements this feature, not an intrinsic ORM or even JPA limitation.

 

Please don't forget to rate!

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. - Antoine de Saint Exupéry

Please visit my blog

02. Jun 2009, 20:31 CET | Link
Arbi Sookazian wrote on Jun 02, 2009 19:39:
I never got a technical explanation (note the closedness of the JCP in this respect) from Mike Keith regarding why he was opposed to MANUAL flush, most likely a political issue, who knows.

I think that the problem is that we do not carefully try to understand the perspective from the other people, we just do not place on their shoes, for example, back when I used EOF I never had this kind of problems, I had others, but transactions were plain easy, all I had to do:


List customers = editingContext.fetch(someQuery)
List merchandises = editingContext.fetch(someQuery)

Customer customer = customers[0];
Customer merchandise = merchandise[0];

Order order =editingContext.create(Order.class);
order.setCustomer(customer);
order.getMerchandises().add(merchandise)

editingContext.saveAllChanges();

And that was it. just a call to saveAllChanges and things were persisted in to the database, I did not had to worry about JDBC, JTA, transaction boundaries, the enditingContext handled it all (even offering nestedEditingContext) and this was more than 10 years ago. Basically no transaction was commited until saveAllChanges, all other queries were done in readonly transparent-transactions why Hibernate (or JPA) can not work that way? why I can not just query stuff in a transactionless (from the JPA user perspective) way and only worry about transactions when I commit? When I tried to explaing FlushMode.MANUAL to the EclipseLink guys they told me EclipseLink would do it (but I am not sure if they actually understood what I was asking for) they told me:

douglas.clarke@xxxxxxxxxx (Doug Clarke) wrote: Making changes within a entity manager acting as an extended persistence context where the complete set of conversation changes are committed in a single transaction does make sense and is very common. JPA supports this through its support for joining of an extended persistence context with a transaction.

So... they seem to believe it is possible to avoid having a an open transaction during user think time using this support for extended persistence context... Are they crazy? or.. what are they talking about?

 

Please don't forget to rate!

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. - Antoine de Saint Exupéry

Please visit my blog

02. Jun 2009, 21:09 CET | Link
@Stateful @ConversationScoped
public class OrderConversation {

    @PersistenceContext(type=EXTENDED) EntityManager em;
    @Current Conversation conversation;
    private Order order;

    public Order getOrder() { return order; }

    public void load(int id) {
        conversation.begin();
        em.setFlushMode(MANUAL);
        order = em.get(User.class, id);
    }

    public void addLineItemByAjax(Product product, int quantity) {
        order.addLineItem( new LineItem(product, quantity) );
    }

    public void removeLineItemByAjax(LineItem li) {
        order.removeLineItem(li);
    }

    public void commitAllChanges() {
        em.flush();
        conversation.end();
    }

}
All changes are written to the database atomically at the end of the conversation. What's not to get?

Yes, from my point of view MANUAL flush mode is very handy and just makes sense in JPA. Gavin are you aware of any discussions in EG to add it to JPA 2?

02. Jun 2009, 22:17 CET | Link

What Doug is trying to say is that you can try to do it this way:

@Stateful @ConversationScoped
@Transaction(NOT_SUPPORTED)
public class OrderConversation {

    @PersistenceContext(type=EXTENDED) EntityManager em;
    @Current Conversation conversation;
    private Order order;

    public Order getOrder() { return order; }

    public void load(int id) {
        conversation.begin();
        order = em.get(User.class, id);
    }

    public void addLineItemByAjax(Product product, int quantity) {
        order.addLineItem( new LineItem(product, quantity) );
    }

    public void removeLineItemByAjax(LineItem li) {
        order.removeLineItem(li);
    }

    @Transaction(REQUIRED)
    public void commitAllChanges() {
        em.isOpen();
        conversation.end();
    }

}

Now, personally, I find this amazingly unnatural. As a side-effect of the @Transaction(REQUIRED) declaration and call to em.isOpen() on commitAllChanges(), the persistence context gets flushed and all the work you did outside of transactions in previous method calls gets committed.

But the bigger problems are:

  1. Persistence context propagation is now broken - if I call a stateless session bean, the persistence context does not propagate, so any work it does is either committed non-atomically (i.e. immediately) or not at all. Work done by stateless session beans is not able to form part of the atomic long-running optimistic transaction.
  2. I now can't perform my reads inside JTA transactions. The reads have to happen with autocommit on, which takes away my ability to ask for transaction isolation. Now, sure, the overarching optimistic transaction is not going to have the isolation semantics of a pessimistic transaction, but now I can't even get repeatable reads inside the individual requests.
 

Learn more about Weld...

02. Jun 2009, 22:31 CET | Link
Rafal Hajdacki wrote on Jun 02, 2009 21:09:
Yes, from my point of view MANUAL flush mode is very handy and just makes sense in JPA. Gavin are you aware of any discussions in EG to add it to JPA 2?

No, it won't be in JPA2. Perhaps in JPA 2.1 I might be able to talk people into supporting some kind of compromise solution using something like this:

@Stateful @ConversationScoped
@Transaction(OPTIMISTIC)
public class OrderConversation {

    @PersistenceContext(type=EXTENDED) EntityManager em;
    @Current Conversation conversation;
    @Current OptimisticTransaction optimisticTransaction;
    private Order order;

    public Order getOrder() { return order; }

    public void load(int id) {
        conversation.begin();
        optimisticTransaction.begin();
        order = em.get(User.class, id);
    }

    public void addLineItemByAjax(Product product, int quantity) {
        order.addLineItem( new LineItem(product, quantity) );
    }

    public void removeLineItemByAjax(LineItem li) {
        order.removeLineItem(li);
    }

    public void commitAllChanges() {
        optimisticTransaction.commit();
        conversation.end();
    }

}

It doesn't quite give you everything you have with FlushMode.NEVER but it might be acceptable to Oracle who, as far as I know, are the only folks objecting to this feature.

 

Learn more about Weld...

02. Jun 2009, 22:59 CET | Link
Gavin King wrote on Jun 02, 2009 22:17:

So, basically your initial example is not really an example on what is so good about FlushMode.MANUAL (because there is a counter example, you wrote it yourself) that shows that theres is an alternative standard way of doing the same thing... So I ask again, can you show me an example that actually shows how the persistence context propagation gets broken by not using FlushMode.MANUAL? An example that could be shown to someone in the EclipseLink team with the message: This is impossible to do in EclipseLink because yo do not have FlushMode.MANUAL and that would leave them baffled.

Now, personally, I find this amazingly unnatural. As a side-effect of the @Transaction(REQUIRED) declaration and call to em.isOpen() on commitAllChanges(), the persistence context gets flushed and all the work you did outside of transactions in previous method calls gets committed.

Ok, so, FlushMode.MANUAL is a shortcut to to basically the same thing an extended persistence context do? Nice but, shouldnt we prefere the standard solution (like Seam did by preferring JSF over Wicket ;-) )

But the bigger problems are: Persistence context propagation is now broken - if I call a stateless session bean, the persistence context does not propagate, so any work it does is either committed non-atomically (i.e. immediately) or not at all. Work done by stateless session beans is not able to form part of the atomic long-running optimistic transaction.

And why is that? Does this mean that extended persistence contexts can only be used in Stateful EJBs? and why it can not be fixed by altering the way extended persistence contexts work but without creating FlushType.MANUAL? What do the guys of EclipseLink do when someone reports this as a bug or as requested feature? Has anyone tried that? Does this mean that extended persistence contexts are actually a feature of stateful EJBs and not a feature usable from Seam POJOs(Specially not the stateless ones) or from a JSE application? )

I now can't perform my reads inside JTA transactions. The reads have to happen with autocommit on, which takes away my ability to ask for transaction isolation. Now, sure, the overarching optimistic transaction is not going to have the isolation semantics of a pessimistic transaction, but now I can't even get repeatable reads inside the individual requests.

I also said something similar to the EclipseLink guys, and this was the answer. If I am going to get inconsistencies between requests, maybe I do not care about getting them between query calls... if that is the case... does that mean that FlushMode.MANUAL is useless for me?

 

Please don't forget to rate!

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. - Antoine de Saint Exupéry

Please visit my blog

02. Jun 2009, 23:48 CET | Link
So I ask again, can you show me an example that actually shows how the persistence context propagation gets broken by not using FlushMode.MANUAL? An example that could be shown to someone in the EclipseLink team with the message: This is impossible to do in EclipseLink because yo do not have FlushMode.MANUAL and that would leave them baffled.

Huh, I just told you what can't be done, I'm sure you have enough knowledge of this stuff to figure out the rest yourself. It's not my job to write examples to help the EclipseLink team improve their product!

But here's a starting point for the kind of things I'm thinking about:

@Stateful @ConversationScoped
public class OrderConversation {

    @Current OrderDao orderDao;
    @Current ProductDao productDao;
    @Current Conversation conversation;
    private Order order;

    public Order getOrder() { return order; }

    public void load(int id) {
        conversation.begin();
        em.setFlushMode(MANUAL);
        order = orderDao.find(id);
    }

    public void addLineItemByAjax(in productId, int quantity) {
        Product product = productDao.find(productId);
        order.addLineItem( new LineItem(product, quantity) );
    }

    public void removeLineItemByAjax(LineItem li) {
        order.removeLineItem(li);
    }

    public void commitAllChanges() {
        em.flush();
        conversation.end();
    }

}

@Stateless 
OrderDao {
    @PersistenceContext EntityManager em;
        
    public Order find(int id) {
        return em.find(Order.class, id);
    }
    
}

@Stateless 
ProductDao {
    @PersistenceContext EntityManager em;
        
    public Product find(int id) {
        return em.find(Product.class, id);
    }
        
}

In this example, the persistence context propagates to the XxxxxDaos, so the Order and the Product belong to the same persistence context, and remain attached to it for the entire optimistic transaction. If you try to use Transaction(NOT_SUPPORTED), this will not be the case. The Order will not be attached when commitAllChanges() is called, and the LineItem changes will not be persisted. I don't think you will be able to rewrite this example without FlushMode.MANUAL.

 

Learn more about Weld...

02. Jun 2009, 23:55 CET | Link
Ok, so, FlushMode.MANUAL is a shortcut to to basically the same thing an extended persistence context do?

No. I explained that to you. Please try reading and understanding before arguing. Geez.

And why is that? Does this mean that extended persistence contexts can only be used in Stateful EJBs?

You can find the answer to this question and more in the JPA 1.0 specification.

and why it can not be fixed by altering the way extended persistence contexts work but without creating FlushType.MANUAL?

Whatever change you would make would be more or less functionally equivalent to FlushMode.MANUAL. Of course you could call it FooBar.IM_BEING_REALLY_DENSE if you prefer.

What do the guys of EclipseLink do when someone reports this as a bug or as requested feature? Has anyone tried that?

I have no idea. Why are you asking me what EclipseLink users do?

Does this mean that extended persistence contexts are actually a feature of stateful EJBs and not a feature usable from Seam POJOs(Specially not the stateless ones) or from a JSE application?

You can find the answers to these questions and more in the JPA 1.0 specification and the Seam documentation.

I also said something similar to the EclipseLink guys, and this was the answer. If I am going to get inconsistencies between requests, maybe I do not care about getting them between query calls... if that is the case... does that mean that FlushMode.MANUAL is useless for me?

I just told you about the problem with persisence context propagation but you decided to deliberately not understand what I was explaining.

 

Learn more about Weld...

02. Jun 2009, 23:58 CET | Link
Perhaps in JPA 2.1 I might be able to talk people into supporting some kind of compromise solution using something like this

Note that I'm not advocating that this is a great solution. I don't think it's better to introduce a whole new kind of transaction notion in EE and then have to define its demarcation and propagation rules than to introduce a new FlushMode. The new FlushMode is a far simpler solution.

 

Learn more about Weld...

03. Jun 2009, 00:19 CET | Link
Gavin King wrote on Jun 02, 2009 23:55:
What do the guys of EclipseLink do when someone reports this as a bug or as requested feature? Has anyone tried that? I have no idea. Why are you asking me what EclipseLink users do?

Well, it seems to me like it would be a nice idea to make those Oracle guys accept FlushMode.MANUAL in to the JPA spec, and I way to that would be to submit a bug in to EclipseLink bugtracker, asking for a way to do something that can only be done with FlushMode.MANUAL, that way they would be forced to implement a comparable solution (or even just accept to add FlushMode.MANUAL to the spec). That is, of course, if they do not dismiss bug without reading and understanding before rejecting them. Geez. :-P

I just told you about the problem with persistence context propagation but you decided to deliberately not understand what I was explaining.

Yes you told me about the problem with persisence context propagation, but I was hoping for a concrete example, you just told me it breaks but did not explain me why it breaks. If you have a link or know a book with a guide that explains why it breaks, that would be good enough for me, but it really be great if you could explain it and provide an example.

Please do not get me wrong, I really appreciate that you take time to answer this questions in this forum, I know you are one of the greatest experts in this stuff, but sometimes you do exactly what you are accusing me of doing, you just start arguing without reading carefully and without trying to see it from the POV of someone without all your knowledge.

OTOH maybe its my Karma from all the times I have been dismissive with people with less knowledge than me... :'(

 

Please don't forget to rate!

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. - Antoine de Saint Exupéry

Please visit my blog

03. Jun 2009, 00:24 CET | Link

Oh, I see that you did provide an example, see, I knew you could no really be a bad guy :-D

 

Please don't forget to rate!

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. - Antoine de Saint Exupéry

Please visit my blog

11. Jun 2009, 00:00 CET | Link

I posted a link to this discussion in the EclipseLink mailing list, and got this answer:

James Sutherland wrote
Not sure I understand but you seem to want to ignore the container JPA transactions correct?

Normally when using EJB any work you do inside a JTA transaction will be committed when that JTA transaction commits, normally at the end of the SessionBean method, or when the JTA transaction is committed explicitly. You seem to want your EntityManager transaction to span multiple server calls, and multiple JTA transactions. For this I think you would want to use an application managed EntityManager. Either do not use JTA at all, just use EntityManager transactions and commit whenever you desire, or use joinTransaction() when you wish to commit to commit along with the active JTA transaction.

So, it seems that an application managed EntityManager can be used to achive conversational behavior... and all without support of FlushMode.MANUAL... If course asked him in return:

Francisco Peredo wrote
And this application managed EntityManager will give this conversational handling of transactions even when used inside @Stateless EJBs? and if it can be used on @Stateless EJBS... Can you offer any insights on why Gavin thinks it can not be used with @Stateless EJBS? (Or am I plain interpreting him wrong?)

But he still has not responded...

What I would really like to understand is if FlushMode.MANUAL actually makes it possible to integrate conversational behavior with persistence in a way that is really impossible to achieve without it, or it is more like a much more convenient way to do things that are possible anyway.

 

Please don't forget to rate!

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. - Antoine de Saint Exupéry

Please visit my blog

11. Jun 2009, 00:04 CET | Link

There is no persistence context propagation for application-managed EntityManagers, of course! Nor is there when there is no JTA transaction active.

 

Learn more about Weld...

11. Jun 2009, 01:54 CET | Link
You seem to want your EntityManager transaction to span multiple server calls, and multiple JTA transactions.

Isn't that what extended container-managed PCs were designed to handle? They are scoped to the lifetime of a SFSB, not just one method/tx. And the SMPC in Seam is conversation-scoped, thus you can use it for multiple SFSBs or JavaBeans, not just one.

I don't understand why he's recommending application-managed EntityManagers. Typically it's recommended to use container-managed EntityManagers in JEE envmts.

In any event, GKing is correct as per section 5.7 of JPA 2.0 spec:

The extended persistence context obtained from the application-managed entity manager is a stand-alone persistence context—it is not propagated with the transaction.

However, the spec does state:

An application-managed entity manager may be either a JTA entity manager or a resource-local entity manager.

Plus, who wants to do trivial stuff like em.close();? Isn't that what the container is for???

 

required reading: Scala and more Scala... www.artima.com

11. Jun 2009, 13:27 CET | Link
Arbi Sookazian wrote on Jun 11, 2009 01:54:
You seem to want your EntityManager transaction to span multiple server calls, and multiple JTA transactions. Isn't that what extended container-managed PCs were designed to handle? They are scoped to the lifetime of a SFSB, not just one method/tx. And the SMPC in Seam is conversation-scoped, thus you can use it for multiple SFSBs or JavaBeans, not just one. I don't understand why he's recommending application-managed EntityManagers. Typically it's recommended to use container-managed EntityManagers in JEE envmts.

Mmmm, I wonder what is the real difference between a container-managed EntityManager and an application managed one, after all, WebBeans should allow me to store any object at the conversation context... why shouldn't it allow me to store an application managed EntityManager ?. And use EntityManager transactions to commit when I desire to do so. It of course wouldn't care about JTA, but isn't FlushMode.MANUAL a way to ignore JTA commits until we decide to not ignore them anymore? And for that, according to Sutherland I can use joinTransaction().

I am not saying this is a better solution than FlushMode.MANUAL, it does sound more cumbersome, I am just saying that from a practical POV it could achieve the same effect.

In any event, GKing is correct as per section 5.7 of JPA 2.0 spec: The extended persistence context obtained from the application-managed entity manager is a stand-alone persistence context—it is not propagated with the transaction. However, the spec does state: An application-managed entity manager may be either a JTA entity manager or a resource-local entity manager. Plus, who wants to do trivial stuff like em.close();? Isn't that what the container is for???

Of course nobody wants to deal with that stuff, and of course FlushMode.MANUAL in combination with Seam is a lot more comfortable than doing what the EclipseLink guys says is the standard way of dealing with this problem, that is not what I am discussing here, what I want to understand (again) if it is plain impossible to do this without FlushMode.MANUAL, or if FlushMode.MANUAL is a convenience api sugar (and I love api sugar, but I like to know when I am using it)

For example what if I where to write (wouldn't this give me an application managed entity manager that would work with its own entitymanager transactions until I decided to join the JTA transaction using joinTransaction() and effectively (but cumbersomely) emulate FlushMode.MANUAL?):



@Produces @ConversationScoped 
public EntityManager getPaymentStrategy() {
 return EntityManagerFactory.createEntityManager();  
}

And then inject the conversation-scoped PC like this:


@Current EntityManager theConversationScopedEntityManager;
 

Please don't forget to rate!

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. - Antoine de Saint Exupéry

Please visit my blog

11. Jun 2009, 13:35 CET | Link

Sorry, made a copy & paste mistake (posted getPaymentStrategy instead of getTheConversationScopedEntityManager), here comes again:

For example what if I where to write (wouldn't this give me an application managed entity manager that would work with its own entitymanager transactions until I decided to join the JTA transaction using joinTransaction() and effectively (but cumbersomely) emulate FlushMode.MANUAL?):


@Produces @ConversationScoped 
public EntityManager getTheConversationScopedEntityManager() {
 return EntityManagerFactory.createEntityManager();  
}

And then inject the conversation-scoped PC like this:


@Current EntityManager theConversationScopedEntityManager;
 

Please don't forget to rate!

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. - Antoine de Saint Exupéry

Please visit my blog