GWT RequestFactory with Set sub-collections - gwt

I have a little problem with RequestFactory regarding persistence of children collections in the shape of Set . I am using gwt 2.5 with requestfactory, and Hibernate4/Spring3 at the backend. I am using the open-session-in-view filter by Spring so that collections can be persisted after findByID in the save method of my DAO. My problem is everything seems to work ok when children collections are based on List , but when they are based on Set , not all of the items from the client reach the server aparently.
My code looks like this:
-The root entity IndicationTemplate:
#Entity
#Table (name = "vdasIndicationTemplate")
#org.hibernate.annotations.Table ( appliesTo = "vdasIndicationTemplate", indexes =
{#Index (name = "xieIndicationTemplateCreateUser", columnNames= {"createUserID"}),
#Index (name = "xieIndicationTemplateModifyUser", columnNames= {"modifyUserID"})})
public class IndicationTemplate extends AbstractEditable <Integer> implements IEntity <Integer>, IDateable, IDescriptable {
//...
private Set <ProposalTemplate> proposalTemplates = null;
//...
#OneToMany (fetch = FetchType.LAZY, mappedBy = "indicationTemplate"
, cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH, CascadeType.DETACH})
public Set <ProposalTemplate> getProposalTemplates () {
return proposalTemplates;
}
public void setProposalTemplates (Set <ProposalTemplate> proposalTemplates) {
this.proposalTemplates = proposalTemplates;
}
//...
}
-The child entity ProposalTemplate of course has the opposite ManyToOne mapping and has 3 sub-collections as well of the same sort with 3 different entities.
-Client-side proxy for root entity:
#ProxyFor (value = IndicationTemplate.class, locator = PersistenceEntityLocator.class)
public interface IIndicationTemplateProxy extends IEntityProxy, IDeletableProxy, IDescriptableProxy {
//....
Set <IProposalTemplateProxy> getProposalTemplates ();
void setProposalTemplates (Set <IProposalTemplateProxy> proposalTemplateProxy);
}
-On the client, i render the attributes of root entity and also the list of children entity. Then the user can update them, and the changes are stored back into the collection like this:
Set <IProposalTemplateProxy> newList = getElementsFromUiSomehow (); //these elements can be new or just the old ones with some changes
indicationTemplate.getProposalTemplates ().clear ();
indicationTemplate.getProposalTemplates ().addAll (newList);
-And then at some point:
requestContext.saveIndicationTemplate ((IIndicationTemplateProxy) entityProxy)
.fire (new Receiver <IIndicationTemplateProxy> ()
-The RequestContext looks something like:
#Service (value = TemplateService.class, locator = SpringServiceLocator.class)
public interface ITemplateRequestContext extends RequestContext {
/** saves (creates or updates) one given indication template */
Request <IIndicationTemplateProxy> saveIndicationTemplate (IIndicationTemplateProxy indicationTemplate);
//....
}
The problem is only 1 child entity is added per request to the collection server-side. For example, indicationTemplate has 2 proposalTemplates, and i add 4 more, then on the server-side saveIndicationTemplate the entity contains only 3 instead of 6. If happens no matter how many entities i have previously and how many i add, i only get 1 more than before on the server. I did check the proxy object right before firing the requestContext method and it is fully loaded, with all of its children. And finally the weirdest thing is, if i replace Set per List (and all subsequent changes), everything works sweet!
May there be any problem why RF fails to transfer all the changes to the server when using Sets instead of Lists?? Btw, i do prefer Sets in this case, so that is why i am asking.
Anyone?
Thanks for helping!

I assume you are hitting this error. It is a known gwt bug which is still unfixed.
https://code.google.com/p/google-web-toolkit/issues/detail?id=6354&q=set&colspec=ID%20Type%20Status%20Owner%20Milestone%20Summary%20Stars
try to use list instead of set and it should be fine.

Related

EF Filtering a Child Table with Lazy Load

I'm using entity framework with POCOs and the repository pattern and am wondering if there is any way to filter a child list lazy load. Example:
class Person
{
public virtual Organisation organisation {set; get;}
}
class Organisation
{
public virtual ICollection<Product> products {set; get;}
}
class Product
{
public bool active {set; get;}
}
Currently I only have a person repository because I'm always starting from that point, so ideally I would like to do the following:
Person person = personRepo.GetById(Id);
var products = person.organisation.products;
And have it only load products where active = true from the database.
Is this possible and if so how?
EDIT My best guess would be either a filter can be added to the configuration of the entity. Or there might be a way to intercept/override the lazy load call and modify it. Obviously if I created an Organisation Repository I could manually load it as I please but I am trying to avoid that.
There's not a direct way to do this via lazy loading, but if you were willing to explicitly load the collection, you could follow whats in this blog, see the Applying filters when explicitly loading related entities section.
context.Entry(person)
.Collection(p => p.organisation.products)
.Query()
.Where(u => u.IsActive)
.Load();
You can do what Mark Oreta and luksan suggest while keeping all the query logic within the repository.
All you have to do is pass a Lazy<ICollection<Product>> into the organization constructor, and use the logic they provided. It will not evaluate until you access the value property of the lazy instance.
UPDATE
/*
First, here are your changes to the Organisation class:
Add a constructor dependency on the delegate to load the products to your
organization class. You will create this object in the repository method
and assign it to the Person.Organization property
*/
public class Organisation
{
private readonly Lazy<ICollection<Product>> lazyProducts;
public Organisation(Func<ICollection<Product>> loadProducts){
this.lazyProducts = new Lazy<ICollection<Product>>(loadProducts);
}
// The underlying lazy field will not invoke the load delegate until this property is accessed
public virtual ICollection<Product> Products { get { return this.lazyProducts.Value; } }
}
Now, in your repository method, when you construct the Person object you will assign the Organisation property with an Organisation object containing the lazy loading field.
So, without seeing your whole model, it will looks something like
public Person GetById(int id){
var person = context.People.Single(p => p.Id == id);
/* Now, I'm not sure about the cardinality of the person-organization or organisation
product relationships, but let's assume you have some way to access the PK of the
organization record from the Person and that the Product has a reference to
its Organisation. I may be misinterpreting your model, but hopefully you
will get the idea
*/
var organisationId = /* insert the aforementioned magic here */
Func<ICollection<Product>> loadProducts = () => context.Products.Where(product => product.IsActive && product.OrganisationId == organisationId).ToList();
person.Organisation = new Organisation( loadProducts );
return person;
}
By using this approach, the query for the products will not be loaded until you access the Products property on the Organisationinstance, and you can keep all your logic in the repository. There's a good chance that I made incorrect assumptions about your model (as the sample code is quite incomplete), but I think there is enough here for you to see how to use the pattern. Let me know if any of this is unclear.
This might be related:
Using CreateSourceQuery in CTP4 Code First
If you were to redefine your properties as ICollection<T> rather than IList<T> and enable change-tracking proxies, then you might be able to cast them to EntityCollection<T> and then call CreateSourceQuery() which would allow you to execute LINQ to Entities queries against them.
Example:
var productsCollection = (EntityCollection<Product>)person.organisation.products;
var productsQuery = productsCollection.CreateSourceQuery();
var activeProducts = products.Where(p => p.Active);
Is your repository using something like:
IQueryable<T> Find(System.Linq.Expressions.Expression<Func<T, bool>> expression)
If so you can do something like this:
var person = personRepo.Find(p => p.organisation.products.Any(e => e.active)).FirstOrDefault();
You could possibly use Query() method to achieve this. Something like:
context.Entry(person)
.Collection(p => p.organisation.products)
.Query()
.Where(pro=> pro.Active==true)
.Load();
Have a look at this page click here

JPQL #NamedQuery with Entities or Ids?

Sorry if duplicated.
Is it possible or recommended for business layer to using objects instead of ids?
SELECT c
FROM Child AS c
WHERE c.parent = :parent
public List<Child> list(final Parent parent) {
// does parent must be managed?
// how can I know that?
// have parent even been persisted?
return em.createNamedQuery(...).
setParameter("parent", parent);
}
This is how I work with.
SELECT c
FROM Child AS c
WHERE c.parent.id = :parent_id
public List<Child> list(final Parent parent) {
// wait! parent.id could be null!
// it may haven't been persisted yet!
return list(parent.getId());
}
public List<Child> list(final long parentId) {
return em.createNamedQuery(...).
setParameter("parent_id", parentId);
}
UPDATED QUESTION --------------------------------------
Do any JAX-RS or JAX-WS classes which each can be injected with #EJB can be said in the same JTA?
Here come the very original problem that I always curious about.
Let's say we have two EJBs.
#Stateless
class ParentBean {
public Parent find(...) {
}
}
#Stateless
class ChildBean {
public List<Child> list(final Parent parent) {
}
public List<Child> list(final long parentId) {
}
}
What is a proper way to do with any EJB clients?
#Stateless // <<-- This is mandatory for being injected with #EJB, right?
#Path("/parents/{parent_id: \\d+}/children")
class ChildsResource {
#GET
#Path
public Response list(#PathParam("parent_id") final long parentId) {
// do i just have to stick to this approach?
final List<Child> children1 = childBean.list(parentId);
// is this parent managed?
// is it ok to pass to other EJB?
final Parent parent = parentBean.find(parentId);
// is this gonna work?
final List<Child> children2 = childBean.list(parent);
...
}
#EJB
private ParentBean parentBean;
#EJB
private ChildBean childBean;
}
Following is presented as an answer only to question "Is it possible or recommended for business layer to using objects instead of ids?", because I unfortunately do not fully understand second question "Do any JAX-RS or JAX-WS classes which each can be injected with #EJB can be said in the same JTA?".
It is possible. In most cases also recommended. Whole purpose of ORM is that we can operate to objects and their relationships and not to their presentation in database.
Id of entity (especially in the case of surrogate id) is often concept that is only interesting when we are near storage itself. When only persistence provided itself needs to access id, it makes often sense to design methods to access id as protected. When we do so, less noise is published to the users of entity.
There is also valid exceptions as usual. It can be for example found that moving whole entity over the wire is too resource consuming and having list of ids instead of list of entities is preferable. Such a design decision should not be done before problem actually exists.
If parent has not been persisted yet, then the query won't work, and executing it doesn't make much sense. It's your responsibility to avoid executing it if the parent hasn't been persisted. But I would not make it a responsibility of the find method itself. Just make it clear in the documentation of the method that the parent passed as argument must have an ID, or at least be persistent. No need to make the sameverification as the entity manager.
If it has been persisted, but the flush hasn't happened yet, the entity manager must flush before executing the query, precisely to make the query find the children of the new parent.
At least with Hibernate, you may execute the query with a detached parent. If the ID is there, the query will use it and execute the query.

Why does JPA do a double insert upon merge()

In EclipseLink, I run into a problem where an element is inserted twice, resulting into a primary key violation. The scenario is as follows:
I have three entities, Element, Restriction and RestrictionElement. The entity RestrictionElement acts as a many-to-many relationship between the two others.
When I create a new RestrictionElement and merge the Element, the RestrictionElement is inserted twice. The code:
// element is an Element, restriction is a Restriction. Both are already in present in the database.
RestrictionElement newRestrictionElement = new RestrictionElement(restriction, element);
Transaction transaction = new Transaction();
em.merge(element); //em is the EntityManager
transaction.commit();
However, if I remove the line restriction.getReferencedRestrictionElements().add(this); the RestrictionElement is inserted once.
Can anyone explain why this happens? Or point to a document that explains how to work out what the merge() command does?
Relevant JPA code: (I'll only given a small part. There aren't any other big problems with the code.)
public class RestrictionElement {
#JoinColumns({#JoinColumn(name = "ELEMENT_ID", referencedColumnName = "ID"),#JoinColumn(name = "ELEMENT_DESCRIPTOR", referencedColumnName = "DESCRIPTOR")})
private Element element;
#JoinColumns({#JoinColumn(name = "RESTRICTION_ID", referencedColumnName = "ID"),#JoinColumn(name = "RESTRICTION_DESCRIPTOR", referencedColumnName = "DESCRIPTOR")})
private Restriction restriction;
public RestrictionElement(Restriction restriction, Element element) {
this.restriction = restriction;
this.element = element;
restriction.getReferencedRestrictionElements().add(this);
element.getReferingRestrictionElements().add(this);
}
}
public class Element {
#OneToMany(mappedBy = "element")
private List<RestrictionElement> referingRestrictionElements = new ArrayList<RestrictionElement>();
}
public class Restriction extends Element {
#OneToMany(mappedBy = "restriction", cascade = { ALL, PERSIST, MERGE, REMOVE, REFRESH })
private List<RestrictionElement> referencedRestrictionElements = new ArrayList<RestrictionElement>();
}
How do your persist RestrictionElement? My guess is when you persist it you get one copy, then a second when you merge the Element with the reference to it.
Try using persist() for new objects, and related the objects after they are managed with the correct managed copy.
I got a similar issue when I run my program, but the issue is not there under step by step debugging.
I resolved the issue by changing List to Set in the OneToMany relationship.
Don't forget that once you retrieve an instance of the class using JPA, the instance becomes managed, any changes to it will be automatically merged into the database.
By default, this merge will occur at the moment you query the table. Therefore the following situation can happen:
query (find by ID)
update (setName = "xx")
query another class that has a direct relationship to this one (find by ID again)
in a situation similar to the above, the second find will effectively issue a merge to the first table. (I'm not sure exactly of the details or scenarios here).
My suggestion is that you issue every single query (findById for example) or every instance you have before you start modifying it (ie, set, etc).
Hope it helps.

JPA: Creating an entity whenever another entity is created

I'm using JPA/Hibernate over PGSQL DB.
I have an entity in my application, and I want to persist another entity (of a different type) every time the first entity is persisted. For example, whenever an "ORDER" is created, I want to immediately persist an empty "ORDER_INVOICE" entity and connect it to the order. These reside in two different tables.
At first I thought about writing a #PostPersist function for the ORDER entity and persisting the ORDER_INVOICE in it, but my problem is that I don't have the Entity Manager in this context.
I'm looking to avoid remembering to persist the ORDER_INVOICE upon every ORDER persistence.
Is that the right way to go? If so, how do I get the EM into the PostPersist? And if not, what would be a better way?
Why don't you simply create it in the constructor of your master entity, and set cascade=persist on the relationship?
#Entity
public class Order {
#OneToMany(mappedBy = "order", cascade=CascadeType.PERSIST)
private List<Invoice> invoices = new ArrayList<Invoice>();
public Order() {
Invoice i = new Invoice();
i.setOrder(this);
this.invoices.add(i);
}
// ...
}
EDITED :
To avoid creating a new invoice each time the Order's constructor is invoked (by JPA, for example), you could use this kind of code :
#Entity
public class Order {
#OneToMany(mappedBy = "order", cascade=CascadeType.PERSIST)
private List<Invoice> invoices = new ArrayList<Invoice>();
/**
* Constructor called by JPA when an entity is loaded from DB
*/
protected Order() {
}
/**
* Factory method; which creates an order and its default invoice
*/
public static Order createOrder() {
Order o = new Order();
Invoice i = new Invoice();
i.setOrder(o);
o.invoices.add(i);
}
// ...
}
If the order is persisted after having been instanciated by the factory method, then the invoice will be persisted as well (thanks to the cascade). If the order is not persisted, then it will be garbage collected at some point, and its default invoide as well.

Convince entity context (EF1) to populate entity references

I have an entity with self reference (generated by Entity Designer):
public MyEntity: EntityObject
{
// only relevant stuff here
public int Id { get...; set...; }
public MyEntity Parent { get...; set...; }
public EntityCollection<MyEntity> Children { get...; set...; }
...
}
I've written a stored procedure that returns a subtree of nodes (not just immediate children) from the table and returns a list of MyEntity objects. I'm using a stored proc to avoid lazy loading of an arbitrary deep tree. This way I get relevant subtree nodes back from the DB in a single call.
List<MyEntity> nodes = context.GetSubtree(rootId).ToList();
All fine. But when I check nodes[0].Children, its Count equals to 0. But if I debug and check context.MyEntities.Results view, Children enumerations get populated. Checking my result reveals children under my node[0].
How can I programaticaly force my entity context to do in-memory magic and put correct references on Parent and Children properties?
UPDATE 1
I've tried calling
context.Refresh(ClientWins, nodes);
after my GetSubtree() call which does set relations properly, but fetches same nodes again from the DB. It's still just a workaround. But better than getting the whole set with context.MyEntities().ToList().
UPDATE 2
I've reliably solved this by using EF Extensions project. Check my answer below.
You need to assign one end of the relationship. First, divide the collection:
var root = nodes.Where(n => n.Id == rootId).First();
var children = nodes.Where(n => n.Id != rootId);
Now, fix up the relationship.
In your case, you'd do either:
foreach (var c in children)
{
c.Parent = root;
}
...or:
foreach (var c in children)
{
root.Children.Add(c);
}
It doesn't matter which.
Note that this marks the entities as modfied. You'll need to change that if you intend to call SaveChanges on the context and don't want this saved.
The REAL solution
Based on this article (read text under The problem), navigation properties are obviously not populated/updated when one uses stored procedures to return data.
But there's a nice manual solution to this. Use EF Extensions project and write your own entity Materilizer<EntityType> where you can correctly set navigation properties like this:
...
ParentReference = {
EntityKey = new EntityKey(
"EntityContextName.ParentEntitySetname",
new[] {
new EntityKeyMember(
"ParentEntityIdPropertyName",
reader.Field<int>("FKNameFromSP")
)
})
}
...
And that's it. Calling stored procedure will return correct data, and entity object instances will be correctly related to eachother. I advise you check EF Extensions' samples, where you will find lots of nice things.