Delete item within owned collection using GWT RequestFactory - google-app-engine

I have a simple 1-n relationship (Product -> Item) mapped with RF EntityProxy. So,
ProductProxy extends EntityProxy {
List <ItemProxy> getItems();
void setItems(List<ItemProxy> items);
}
I have also a Product Editor with a nested ListEditor for Items. Everything is working fine if I Add new a Item to product.items list or edit any of them (save successfully).
However, If I remove one Item from the ProductProxy.getItems().remove(index) and try to save that product as a whole I noticed that when the object arrives on the server side, the item I've just removed is still within the collection.
It seems to me that RF tries a lookup for the objects into the datastore (using the Locator) before injecting the new values into the service object.
I need basically to be able to remove an Item within the collection and save the new (modified) collection into the Product object.
Thanks!!
PS. I'm using Objectify Ref<> to keep that collections.
Payload before sending request:
{"F":"web.app.gwt.shared.AppRequestFactory","O":[{"T":"kKv$zKrUQuvZDqvbc2XdTq6i1qU=","V":"NC4w","P":{"defaultOptions":[]},"S":"IjI5MiI=","O":"UPDATE"},{"T":"_dEu_lZqt6BooJQsjzBeHUf38EY=","V":"NC4w","S":"IjI5MCI=","O":"UPDATE"},{"T":"_dEu_lZqt6BooJQsjzBeHUf38EY=","V":"NC4w","S":"IjI4OSI=","O":"UPDATE"},{"T":"_dEu_lZqt6BooJQsjzBeHUf38EY=","V":"NC4w","S":"IjI5MSI=","O":"UPDATE"}],"I":[{"P":[{"T":"kKv$zKrUQuvZDqvbc2XdTq6i1qU=","S":"IjI5MiI="}],"O":"O4GgjqqjQkeFcxD6lGwHruEwO6U="}]}

Related

AngularJS - How to add child objects during edit and then PUT

I'm getting started with AngularJS with Web API and EF on the back end. I have an edit form that is populated via a GET request which returns a Boat object. One of Boat's properties is an Images array.
If the user adds images to Boat then I need records to be inserted into the database for each new image when the boat is updated. (But obviously not for images that the boat already had prior to edit.)
The current Web API function is:
public async Task<IHttpActionResult> Put(int id, Boat boat)
It seems I could either:
a) Push any newly added images to $scope.Boat.Images prior to the PUT. Then in the Web API function, loop through the received Boat.Images, check if a database record exists for that image, if no record exists add the image record to the database. This seems a bit uneconomical because I'm looping through every existing image and checking if it actually exists in the db already.
or
b) Send a separate object "newImages" with the PUT. Then I guess the Web API function would be:
public async Task<IHttpActionResult> Put(int id, Boat boat, string[] newImages)
This would have the benefit of not having to check which images already exist vs new ones. ie. Everything in newImages gets added to the database. But, is it weird from an AngularJS point of view to separate the new images from the Boat.Images collection?
Would you do a) or b) or... c) some other way?
I'll do A as it fits more the Restful approach.
Now Images could be an Array of complex object instead of Array of string, therefore you would have a property ID.
Then on the WebAPI side, you just add the Images without IDs set.
var newImages = Boat.Images.Select(x => x.Id == null);

Sorting and Filtering a collection in a Paged ListBox

I have a database with 10,000 items, to which you can add and remove while the app is running.
I have a ListBox that displays at most 100 items, and supports paging.
You can filter and sort on the 10,000 items, which needs to be immediately reflected in the listbox.
I have a button that randomly selects an item as long as it passes the filters.
What is the best set of collections/views to use for this kind of operation?
So far, my first step will be to create an ObservableCollection of ALL items in the database which we will call MainOC.
Then create a List of all items that match the filter by parsing MainOC which we will call FilteredList.
Then create a ListCollectionView based on the above List that holds the first 100 items.
CONS:
You have to recreate the ListCollectionView every time a sort operation is applied.
You have to recreate the ListCollectionView every time you page.
You have to recreate the ListCollectionView every time a filter is changed.
You have to recreate the ListCollectionView every time an item is added or removed to MainOC.
Is there a better approach that I am missing?
For example, I see that you can apply filters to a ListCollectionView. Should I populate my ListCollectionView with all 10,000 items? But then how can I limit how many items my ListBox is displaying?
Should I be doing my filtering and sorting directly against the database? I could build FilteredList directly off the database and create my ListCollectionView based off that, but this still has all the cons listed above.
Looking for any input you can provide!
This is a problem which is easily solved using DynamicData . Dynamic data is based on rx so if you are not familiar with the wonderful Rx I suggest you start learning it. There is quite a bit of a learning curve but but the rewards are huge.
Anyway back to my answer, the starting point of dynamic data is to get some data into a cache which is constructed with a key as follows
var myCache = new SourceCache<MyObject, MyId>(myobject=>myobject.Id)
Obviously being a cache there are methods to add, update and remove so I will not show those here.
Dynamic data provides a load of extensions and some controllers to dynamically interrogate the data. For paging we need a few elements to solve this problem
//this is an extension of observable collection optimised for dynamic data
var collection = new ObservableCollectionExtended<MyObject>();
//these controllers enable dynamically changing filter, sort and page
var pageController = new PageController();
var filterController = new FilterController<T>();
var sortController = new SortController<T>();
Create a stream of data using these controllers and bind the result to the collection like this.
var mySubscription = myCache.Connect()
.Filter(filterController)
.Sort(sortController)
.Page(pageController)
.ObserveOnDispatcher() //ensure we are on the UI thread
.Bind(collection)
.Subscribe() //nothing happens until we subscribe.
At any time you can change the parameters of the controllers to filter, sort, page and bind the data like follows
//to change page
pageController.Change(new PageRequest(1,100));
//to change filter
filterController.Change(myobject=> //return a predicate);
//to change sort
sortController .Change( //return an IComparable<>);
And as if by magic the observable collection will self-maintain when any of the controller parameters change or when any of the data changes.
The only thing you now have to consider is the code you need for loading the database data into the cache.
In the near future I will create a working example of this functionality.
For more info on dynamic data see
Dynamic data on Github
Wpf demo app

Do Fluent conventions break lazy loading? (uNhAddIns)

I have a simple entity class in a WPF application that essentially looks like this:
public class Customer : MyBaseEntityClass
{
private IList<Order> _Orders;
public virtual IList<Order> Orders
{
get { return this._Orders; }
set {this._Orders = new ObservableCollection<Order>(value);}
}
}
I'm also using the Fluent automapper in an offline utility to create an NHibernate config file which is then loaded at runtime. This all works fine but there's an obvious performance hit due to the fact that I'm not passing the original collection back to NHibernate, so I'm trying to add a convention to get NHibernate to create the collection for me:
public class ObservableListConvention : ICollectionConvention
{
public void Apply(ICollectionInstance instance)
{
Type collectionType =
typeof(uNhAddIns.WPF.Collections.Types.ObservableListType<>)
.MakeGenericType(instance.ChildType);
instance.CollectionType(collectionType);
}
}
As you can see I'm using one of the uNhAddIns collections which I understand is supposed to provide support for both the convention and INotification changes, but for some reason doing this seems to break lazy-loading. If I load a custom record like this...
var result = this.Session.Get<Customer>(id);
...then the Orders field does get assigned an instance of type PersistentObservableGenericList but its EntityId and EntityName fields are null, and attempting to expand the orders results in the dreaded "illegal access to loading collection" message.
Can anyone tell me what I'm doing wrong and/or what I need to do to get this to work? Am I correct is assuming that the original proxy object (which normally contains the Customer ID needed to lazy-load the Orders member) is being replaced by the uNhAddIns collection item which isn't tracking the correct object?
UPDATE: I have created a test project demonstrating this issue, it doesn't reference the uNhAddins project directly but the collection classes have been added manually. It should be pretty straightforward how it works but basically it creates a database from the domain, adds a record with a child list and then tries to load it back into another session using the collection class as the implementation for the child list. An assert is thrown due to lazy-loading failing.
I FINALLY figured out the answer to this myself...the problem was due to my use of ObservableListType. In NHibernate semantics a list is an ordered collection of entities, if you want to use something for IList then you want an unordered collection i.e. a Bag.
The Eureka moment for me came after reading the answer to another StackOverflow question about this topic.

Does everything in Marionnette have to be an object or collection

I am writing an app which will send orders to a remote server. I have a lot of the logic done now for setting up new orders. Items are added to a cart, cart totals are created and I am now ready to hit the server endpoint. At the moment, the REST API (which is being built by a separate team) needs me to:
Send a new order request and receive a new order number
Loop through my cart sending each item individually to the new order endpoint
Send the order totals
Send the payment options and amounts
Return the final data as a receipt to the customer
I currently have
- A cart collection which contains item models
- A totals model
I am not looking for code particularly but could someone outline a method to send the data to the server. I'm trying to figure how to use collections and API URI endpoints to do this but don't have any precedent to follow. Would it be natural in a Marionette/Backbone app to use direct POST requests to the server using defferds and promises or is there a better approach?
I would appreciate any pointers in the right direction,
Generally you wouldn't/shouldn't need to use direct POST requests when interacting with a REST API. Backbone models and collections are designed to interact with an API following this model out of the box.
If you define a collection as so:
var Items = Backbone.Collection.Extend({ url: '/items' });
var myItems = new Items();
myItems.fetch();
then when you call 'fetch' on the collection a GET request will be issued to your specified URL which will populate the collection with the models returned. You can add models to this collection which will fire the appropriate requests to the endpoint. eg. a POST. the default mappings are below for the above collection:
create -> POST '/items'
read -> GET '/items[/id]'
update -> PUT '/items/id'
delete -> DELETE '/items/id'
A lot of this is overridable and configurable so that you can fit into the API that your building against.

Flex 4 data management - how do I approach this?

quite an explanation here, hope someone has the patience to read it through
I'm building an application in Flex 4 that handles an ordering system. I have a small mySql database and I've written a few services in php to handle the database.
Basically the logic goes like this:
I have tables for customers, products, productGroups, orders, and orderContent
I have no problem with the CRUD management of the products, orders and customers, it is the order submission that the customer will fill in that is giving me headaches:
What I want is to display the products in dataGrids, ordered by group, which will be populated with Flex datamanagement via the php-services, and that per se is no problem. But I also want an extra column in the datagrid that the user can fill in with the amount he wishes to order of that product. This column would in theory then bind to the db table "orderContent" via the php services.
The problem is that you would need to create a new order in the database first that the data could bind to (orderContent is linked to an order in the db).
I do not want to create a new order every time a user enters the page to look at the products, rather I would like to create the order when a button is pressed and then take everything from the datagrids on the page and submit it into the database.
My idea has been to create a separate one-column datagrid, line it up next to the datagrid that contains the products and in that datagrid the user would be able to enter the amount of that product he'd like to order.
I've created a valueObject that contains the data I would need for an order:
Code:
package valueObjects
{
public class OrderAmount
{
public var productId:int;
public var productAmount:int;
public var productPrice:Number;
public function orderAmount()
{
}
}
}
My idea was to use a service to get all products from a certain group, populate an ArrayCollection with the data, then transfer each object in that ArrayCollection to an instance of the Value Object above, add the value object to another ArrayCollection that would the be used as a dataProvider for the one-column datagrid (I would only display amount which would be set to zero at first, but use the other data upon transfering it to the db)
I've tried to use the results from the automatically generated serviceResults that retrieve the products for the datagrid and put in a resultHandler that transfers the valueobjects, however this does not seem to work.
Basically my question is this: Am I approaching this thing completely wrong, or is there a way I can get it to work the way I planned?
Would I need to create a completely new service request to get the product id:s, and price to populate the one-column datagrid.
I'll post some code if that would help.
Thank you if you read this far.
Solved it by creating a Value Object class to hold all the info needed for each row in the grid and from the php service that returned all products in a group, I looped through the result and transfered the data needed into my Value Object.
I then added each Value Object into an ArrayCollection and made that the dataProvider for the dataGrid.
No need to use two grids. I forgot how logic things get when you think of datagrid data just as an ArrayCollection and forget the visual presentation of it on screen.
Put in a few itemRenderers and the whole thing is beautiful!

Resources