I am writing a JSF 2.0 form to edit a JPA #Entity object. I have a backing bean that has a get method for the Entity, which it fetches from the EntityManager. So far so good.
The question is does the Entity object that is being edited by the user get accessed by other parts of the application? In other words if someone else calls up that record, do they see the field changes before I merge the record back into the data base via the EntityManager? Or do they get a different instance.
The reason this is important is that the user can enter all sorts of bad data. The validation phase done by the backing bean will not call merge() all the errors are cleared, but what about before then?
If this is a common instance, how do I avoid this problem?
The question is does the Entity object that is being edited by the user get accessed by other parts of the application? In other words if someone else calls up that record, do they see the field changes before I merge the record back into the data base via the EntityManager? Or do they get a different instance.
The entity instance used by JSF will be a detached entity instance. It is not one that belongs to the persistence context. Each client/user will also receive it's own instance of the detached entity.
The reason this is important is that the user can enter all sorts of bad data. The validation phase done by the backing bean will not call merge() all the errors are cleared, but what about before then?
The merging of any invalid data will occur on when you invoke EntityManager.merge to merge the contents of the detached entity with the persistence context. If you never invoked merge, then the modified contents of the Entity will never make it to the persistence context.
If this is a common instance, how do I avoid this problem?
You can always avoid this by validating the state of the entity before merging it with the persistence context. You could employ bean validation in both JSF and JPA, to prevent this scenario, although you will typically do this only in one layer, to prevent redundant checks. However, if you have specified validation groups for your bean validation constraints to distinguish between presentation and persistence constraints, then you ought be employing bean validation in both the layers. Do keep in mind, that once the contents of the bean have been merged successfully with the persistence context, there isn't a lot you can do to undo this change, except for a transaction rollback, or a refresh/clear of the persistence context.
Adding to the correct answer of Vineet:
You could possibly have an attached entity returned by your backing bean, for instance if you used a stateful session bean (EJB) with the extended persistence context.
In this case however you would still not risk concurrency issues, since every instance of a persistence context returns unique instances of attached entities (unique: instance not shared with other existing persistence contexts).
Furthermore, JSF will not push changes into the model (the attached JPA entity in this case) if any kind of validation error occurs. So as long as you have your validation set up correctly (bean validation or regular JSF validation), there will be no risk of 'tainting' the entity.
Additionally, note that for the attached case you would not have to call merge(), as this will automatically happen when the context closes, so instead you 'close' the stateful bean.
That said, the common case is the one Vineet describes where you get a detached entity.
Related
Consider an aggregate with many properties. For example UserGroup. If I want to publish a UserGroupCreatedEvent I can do 2 things:
duplicate the properties from the just created UserGroup to
UserGroupCreatedEvent and copy their values. OR:
Refer to the new UserGroup within the UserGroupCreatedEvent
In many examples, like Axon's Contacts App, I've seen property duplication. I wonder why, and if in real-world CQRS applications, this is not a lot of overhead, and developers choose to refer the aggregate instead.
An event is a DTO and it's meant to cross boundaries. Including the aggregate directly has the following problems:
The aggregate is a concept that makes sense only in its own bounded context;
An event should contain only the relevant changes, not the whole state of the concept;
Because an event is a DTO, at one point it will be (de)serialized and that would be a technical problem with properly encapsulated objects;
Every component/context receiving handling the event would have a dependency of the component where the aggregate is defined;
These are the main reasons why a Domain Event should be just a flattened representation of the relevant state changes.
P.S: If you need to include the whole state in your event, maybe the events is improperly designed or you're dealing with a simple data structure. Usually an aggregate contains some value objects and/or encapsulates some business constraints.
An important property of domain events is that they are immutable. Bearing that in mind, the two possibilities you mention differ greatly:
Duplicating properties records their value at the time the UserGroup was created.
Referencing the UserGroup by ID just tells you that a UserGroup was created, but not the properties it had at the time. If the UserGroup has been deleted in the meantime, this means that the information is lost.
Which properties you copy depends on just that difference. Do you need to be able to look up e.g. the name of a UserGroup at its creation time? Add it as a property. If not (and if it's not expected that it ever will be required), don't.
Also, domain events have a global scope (i.e. they are meaningful outside of your BC), so you should include all information that clients outside of your BC need to make sense of the domain event.
Note that attaching the whole aggregate root object to a domain event violates the immutability rule of domain events, so this is most probably a bad idea.
Even though I use a specific ORM framework, Bold for Delphi, I'm more interested in framework agnostic theoretical view on the problem.
So the question is about having a persistent object and a transient attribute with initial value tag.
The initial tag specifies the value attribute will get when instance of owning object is created.
However when subsequently loading this object from persistence, what should be the value of transient attribute?
Should initial value tag be applied again? Logically, it should, otherwise it will be left unassigned (null).
I couldn't find any specs on this particular case in any of the docs.
We can't create object up to the DB record only - because we would lose all transient attributes. So, when you are loading a persistent object, it can be done only into the already created instance. And there is no other way of instantiating without using the base object constructor, which sets the initial values. Of course, some language could make a workaround about it, but why?
I'm a novice with domain driven design and learning to apply it in my current project. I hope some of you guys have already walked the path and can help me out.
I have a question with regard to saving UI changes back to an Entity (Order).
The scenario:
a. An approver opens the Order (Aggregate root) pending approval on the Web. Makes some changes and clicks the button "Approve".
b. The UI translates the Order changes to a DTO and posts it across to a Web service for processing.
c. The service pulls the Order from OrderRepository via say call to orderRep.GetByID(ApplicationNumber)
Question
1. How do I post the UI changes available in the OrderDTO to Order?
2. What are the different things I need to take care while hydrating the Order?
(If we have to ensure that the domain object (Order) doesn't land up in
invalid state due to changes)
Each user operation should correspond to a different command method in the application service layer. Much of the time it will correspond to exactly one call on a domain object.
You probably don't have fine-grained enough methods on your Order domain object.
Approve() should probably only be a method, not a public setter. Throw an exception within Approve() if it would place the Order object in an invalid state.
Please share your view on this kind of thing i'm currently testing out :
Have an JPA entity inside my JSF managed bean
Bind the entity's properties to the JSF form elements like input text, combo, even datatable for the entity's list of detail objects for example.
Have the entity processed by a service object, meaning the entity object itself, and perhaps with some other simple variables / objects
The service will do some basic validation or simple processes, and deliver the entity object to the DAO layer to be persisted
And the JSF view will reflect on the detached entity
Is this kind of solution with passing the entities between tiers OK ?
Forgive me for my inexperience in this matter, since i was used to play with 'variables' in webapp (using map based formbean in struts 1), but i've read about transforming the entity objects into some other format, but i'm not sure what it is for ?
If the relations between entities are defined, we can bind it to JSF components, and therefore render based on and populate the entity's properties.
Yes, this is perfectly fine and in fact the recommended way to do it nowadays.
This "transforming the entity objects into some other format" refers probably to the Data Transfer Object pattern, which was necessary in the bad old days before annotations, when entity classes usually had to inherit from some framework-specific base class, undergo bytecode manipulation or were implemented as proxy objects by an EJB container.
Such entity objects were either impossible to serialize or contained much more state than the actual entity data and therefore would waste a lot of space when serialized. So if you wanted to have a separate app server tier, you had to use the DTO pattern to have it communicate efficiently with the web tier.
I'm looking for some advice on architecture for a client/server solution with some peculiarities.
The client is a fairly thick one, leaving the server mostly to peristence, concurrency and infrastructure concerns.
The server contains a number of entities which contain both sensitive and public information. Think for example that the entities are persons, assume that social security number and name are sensitive and age is publicly viewable.
When starting the client, the user is presented with a number of entities, not disclosing any sensitive information. At any time the user can choose to log in and authenticate against the server, given the authentication is successful the user is granted access to the sensitive information.
The client is hosting a domain model and I was thinking of implementing this as some kind of "lazy loading", making the first request instantiating the entities and later refreshing them with sensitive data. The entity getters would throw exceptions on sensitive information when they've not been disclosed, f.e.:
class PersonImpl : PersonEntity
{
private bool undisclosed;
public override string SocialSecurityNumber {
get {
if (undisclosed)
throw new UndisclosedDataException();
return base.SocialSecurityNumber;
}
}
}
Another more friendly approach could be to have a value object indicating that the value is undisclosed.
get {
if (undisclosed)
return undisclosedValue;
return base.SocialSecurityNumber;
}
Some concerns:
What if the user logs in and then out, the sensitive data has been loaded but must be disclosed once again.
One could argue that this type of functionality belongs within the domain and not some infrastructural implementation(i.e. repository implementations).
As always when dealing with a larger number of properties there's a risk that this type of functionality clutters the code
Any insights or discussion is appreciated!
I think that this is actually a great example of using View Models. Your concern seems directly related to the consumption of the entities, because of the data that they contain. Instead of passing your entities all the way up to the UI, you could restrict them to live within the domain only - i.e. no entities are passed into or out of the domain at all, with most/all activities done with a command/query approach on the repositories. Repositories would then return a view model instead of the entity.
So how/why does this apply? You could actually have two different view models. One for authenticated and one for non-authenticated users. You expose the actual values for the sensitive data in the authenticated view model and not for the non-authenticated one. You could have them derived from a common interface, and then code against the interface instead of the object type. For your concrete implementation of the non-authenticated user, you can just populate the non-sensitive data, leaving the sensitive getters to do what you want them to do.
My opinion on a couple of points:
I am not a fan of lazy loading in entities. Lazy loading is a data access responsibility and not really part of the model. For me, it is a first-class member of the things I vehemently avoid in my domain, along with paging and sorting. As for how to relate these items together, I would rather loosely couple the objects via ID pointers to other entities. If I want/need the data contained by one of these entities, then I can load it. It is kind of like lazy loading in a way, but I enforce that it never happens in the domain model itself by doing this.
I am not a fan of throwing exceptions on getters. Setters, on the other hand, is fine. I look at it this way. The entity should always be in a valid state. Getters will not impact the state of the entity - setters will. Throwing on a setter is enforcing the integrity of the model. Using the two view model approach would allow me to move the logic to the presenter. So, I could basically do something like "if user is of type non-authorized, do this; otherwise do something else". Since what you are referring to would ultimately be a case of how the data is presented to the user, and not important to the model, I think it fits well. In general, I use nullable types for my properties that can be null and do not enforce anything on the getters, as it is not part of its responsibility, usually. Instead, I use roles to determine what view model to use.
The obvious drawback is that there is more coding required to use the view models, but it comes at the obvious benefit of decoupling presentation and views from the domain. It also will help in unit/integration testing, where you can verify that a certain view model cannot return a type of data.
However, you can use something akin to AutoMapper (depending on what your platform is) to help in populating your view model from your entities.
I made the mistake of posting the question without creating an OpenId so it looks like I'll have to comment here(?).
First of all, thanks for taking you time to answer - It certainly has more to do with how data is presented than how the model works. However, I feel the need to clarify a few things.
The domain model / entities are never referenced directly from the UI. I'm using a variant of the DM-V-VM pattern for UI/business model separation. For lazy loading and repository implementation in general I have entity implementations in a infrastructure layer where things like serialization, dirty tracking and lazy loading is handled.
So the domain layer has entities like:
class Entity {
virtual string SocialSecurityNumber { get; }
}
And the infrastructure layer adds some other functionality to be able to update and restore entites from a server:
class EntityImpl : Entity {
bool isDirty;
bool isLoaded;
// Provide the means to set value on deserialization
override string SocialSecurityNumber;
}
So the lazy loading behavior would be implemented in the infrastructure layer and never seen by the domain layer.
I agree that throwing on getters wouldn't be nice but my concerns are on how an anonymous view model would retrieve the data. As of now, to retrieve a list of entities the viewmodel would hold a reference to a domain repository, should I have two repositories, one for authenticated(and therefore disclosed) entities, and another one for the unauthenticated users - maybe even two different entities?