What's the default nature of Indexing for entity fields in Objectify (version 5)?
Objectify Introduction Page mentions that all fields are indexed with exceptions.
By default, all entity fields except Text and Blob are indexed.
Best Practices page mentions that fields are not indexed by default.
Objectify does not index anything by default; you must explicitly request it with the #Index annotation. Use it wisely.
These 2 statements contradict. What's the default Indexing nature for below class? Are the fields indexed?
#Entity
class Foo {
Long id;
String attributeA;
String attributeB;
}
As clearly stated in bold at the top of IntroductionToObjectify, that page documents the obsolete v3 of Objectify. It is an old wiki page preserved for historical reasons.
BestPractices (and every other page not explicitly marked as obsolete) reflects the current (v5) version of Objectify. Fields are not indexed by default.
Related
I have an oData model with a couple of one-to-many relationship, say person->addresses and person->driving-licences. I would like to be able to sort the result set based on properties in the address entity and driving licence entity. As there could be more than one address, I would initially select a single item from the addresses set, based on a property called IsPrimary. As there could be more that one driving licence, I would select the 'UK' driving licence. Is this possible?
I was hoping I could do something like:
/people?$expand=addresses($filter=isPrimary eq true),drivinglicences($filter=country eq 'UK')&$orderby=addresses/postcode,drivinglicences/active
Unfortunately I get the following error:
"The query specified in the URI is not valid. The parent value for a property access of a property 'isPrimary' is not a single value. Property access can only be applied to a single value."
Does anyone know if what I'm trying to do is supported by the spec? Or whether it is an issue with my query? Or whether it is an issue with the .NET library.
I'm using:
Microsoft.AspNet.OData - 7.2.3
Many Thanks.
What you see here is by design, or rather not supported by the specification, the error message even highlights the only type of expressions supported:
The query specified in the URI is not valid. The parent value for a property access of a property 'isPrimary' is not a single value. Property access can only be applied to a single value.
So the simplest solution is to modify the API either to include a Function bound to the people collection that applies the $filter or $order directly, or a Function that returns the data in a new shape, one that only has perhaps a singleton PrimaryAddress property. How you include driving license in this result is up to you, it could even be a parameter to the function, perhaps your people controller has a queryable function with this signature:
[EnableQuery]
public IHttpActionResult WithLicences(string countryCode)
However that is out of the scope of OPs question about specific syntax support
Although it seems like an important feature, we must remember that $select (Projection) and $filter are evaluated at different points in time, OData queries follow a similar execution sequence to SQL however the filter criteria and $orderby are evaluated separately, and the projection of the resultset is the last evaluation to be applied.
Due to $filter and $orderby being applied independently, neither concept is even aware of the other and as such neither can reference or assume to be applied before the other.
You can prove this by specifying a field in the $orderby and/or $filter that is not included in the $select, you can even reference singleton navigation fields that are not included in an $expand and the query will evaluate correctly.
The OData spec is similar to a law document, in that to properly understand and apply it we need to understand the original intent of the authors. We can get an initial understanding from the early listing of Addressing Entities
Addressing Entities describes functions that can be bound to collections or entities that return either a single entity or a collection of entities
By allowing special provision of custom functions to be applied the authors are encouraging API designers to provide natural extensions to their resource endpoints that can facilitate the execution of pre-determined queries that may be otherwise complex or problematic to express in pure OData query syntax.
In other words, we are encouraged to customise our APIs to make them easier for the end process to consume, and to guide the consuming developer to make the best use of the API, they shouldn't have to discover everything from first principals.
To achieve OPs type of query in pure SQL would still require either a nested lookup, CTE or self join... advanced syntax. In OData v4, the specification does not provide a syntax for targeting specific items within a collection for path expressions (of which $orderby derives from)
5.1.1.15 Path Expressions
Properties and navigation properties of the entity type of the set of resources that are addressed by the request URL can be used as operands or function parameters, as shown in the preceding examples.
Properties of complex properties can be used via the same syntax as in resource paths, i.e. by specifying the name of a complex property, followed by a forward slash (/) and the name of a property of the complex property, and so on,
Properties and navigation properties of entities related with a target cardinality 0..1 or 1 can be used by specifying the navigation property, followed by a forward slash (/) and the name of a property of the related entity, and so on.
If a complex property is null, or no entity is related (in case of target cardinality 0..1), its value, and the values of its components, are treated as null.
RE: I couldn't find anything explicit in the spec. :)
That is the very thing about the OData specification,the specification does not list what is not supported, only what should be supported. So by omission, if you cannot find a reference to how to do something, then that something is not required to be supported.
Introduction http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part2-url-conventions.html#sec_Introduction ... This specification defines a set of recommended (but not required) rules for constructing URLs to identify the data and metadata exposed by an OData service as well as a set of reserved URL query string operators, which if accepted by an OData service, MUST be implemented as required by this document.
This has been on ongoing discussion held in may threads, recently https://stackoverflow.com/a/55324393/1690217
Many people complain that this is surely a fundamental feature of a data access platform, however it is important to respect the original intent of the OData platform and keep our APIs simple by providing customised endpoints to suit our business domain.
I am trying to adopt the Symfony workflow component to my app.
As documentation says marking_store points to string. I was googling for it - it can be a string or json_array-field of a Doctrine entity.
But what if I have an Entity BlogPost with a relation BlogPostStatus that have two fields: some primary id and statusName. Can I configure the workflow component to change statuses of my BlogPost (i.e set new BlogPostStatus to BlogPost entity) and persist it to database?
Now I have only one solution: Add to my BlogPost entity non-mapped field and when it's changed change status of Entity.
Do you have a better solution?
For all built-in marking_store implementations the following is true:
If the functions setMarking or getMarking exist on the object holding the state, they will be used to set or get the marking respectively.
There are 3 built-in marking stores, the SingleStateMarkingStore (using the property accessor, hence setMarking/getMarking), the MultiStateMarkingStore (same), the MethodMarkingStore (explicitly calling those functions, you can change the function via the property setting of your marking_store config).
The difference lies within the argument provided in the setMarking call, for single state (this is the state_machine type, and by default NOT the the workflow type), the argument is the place (or state) where the mark is placed. For multi state (workflow type by default), the argument is an array where the keys are places and the values are marks, usually the marks are 1, and empty places are omitted.
So, I'll assume that your BlogPost (currently) only has a single state at any given time, and what you have to do now is to transform the marking given into the status entity - I will assume your workflow has type state_machine:
/** in class BlogPost */
public function setMarking(string $marking/*, array $context*/) {
$this->status->statusName = $marking;
}
public function getMarking() {
return $this->status->statusName;
}
special cases
If the BlogPostStatus should be a different one (for example, a constant object), then you'd have to use the new interface that dbrumann linked, and hook into the event to add that to the context.
If the BlogPostStatus may not exist at the time of the setMarking/getMarking, you have to create it on the fly in the setter and check for it in the getter. But I'm sure you're capable of doing that ;o)
Also if you're not using the single state workflows but multi state instead, you have to find a way to transform the array of (places->marks) into your status object and vice versa.
I have a #OneToMany JPA association with an instance of Curriculum having several instances of WorkExperience.
The issue I have is that I want to be able to persist one Curriculum together with several WorkExperiences in a single entity manager persist/save call.
I am not sure how to glue several instances of WorkExperiences coming from a regular HTTP POST of a html form to a java collection/set in the Spring MVC model attribute...
First of all, is this possible at all? If so is it a good idea and what kind of html can post collections/arrays of data in a regular HTTP POST?
The Curriculum JPA entity:
#Entity
public class Curriculum {
...
#OneToMany
private Set<WorkExperience> workExperiences;
...
The WorkExperience JPA entity:
#Entity
public class WorkExperience {
...
Yes, it is possible. Spring MVC supports sending Lists/Maps as form values. The way that works is by subscripting the value. For a List, you use the list number, like
<form:input path="myVal[1].property" />
And for a Map you use the map key like
<form:input path="myVal[key].property' />
This is assumming your Model Attribute has a List/Map of said item. I would recommend using a DTO and translating to your Entity. It may be overkill, but I have a problem with allowing the View to manipulate my Entity objects directly.
Also to note: You will have to do some View-side coding to dynamically add/remove items on the form. This can be a real pain, as deletes don't work like you would imagine. Spring MVC has the ability to add to a List/Map, alter the items in a List/Map, but I haven't found a way to remove items from a map directly. I usually handle removes by adding a "remove" boolean flag into my DTOs, then tracking removals by simply adding a form:hidden element for that item in the List/Map, and clean the List/Map on the server-side when I get it.
Once you get all your Entities on the Server-side, then you have to store them. If you want this to be more auto-magic, simply set an annotaion on your parent Entity like
#OneToMany(cascade=CascadeType.PERSIST)
There are several CascadeTypes available, so pick the one that makes sense.
I'm developing my first Spring 3 webapp. In Spring 2, we used to have formBackingObject load data from the database, then let Spring binding update some of the fields, and then onSubmit would persist those changes.
In Spring 3 it seems I have two options:
Let the user edit 100% of the persistent object. This would mean that the object's ID would need to be a hidden field
Create a form object which holds the editable data, and then map that onto the persistent object on submit
The first option is not truly an option, we cannot let the user edit all fields, and we'd rather not present data in hidden fields where anyone capable of pressing F12 can alter the values.
The second option seems like a decent design approach. However, it appears that it requires to essentially clone every editable, persistent class.
#Entity
public class Company {
private String uuid; // not editable!
.. 30 other properties, 2 are not editable
}
public class CompanyForm {
.. 28 of above properties
}
and then some mapping mechanism with lots of
public void map(CompanyForm cf, Company c) {
cf.setName(c.getName());
.. 27 other set(get())
}
I'm praying this is not the "as designed" approach of Spring's MVC binding. However, all tutorial I've found so far are terribly trivial and implement option 1 from above. Does anyone have some suggestions for implementing option 2?
Thanks, Simon
DataBinder API
Note that there are potential security implications in failing to set an array of allowed fields. In the case of HTTP form POST data for example, malicious clients can attempt to subvert an application by supplying values for fields or properties that do not exist on the form. In some cases this could lead to illegal data being set on command objects or their nested objects. For this reason, it is highly recommended to specify the allowedFields property on the DataBinder.
You can use it together with option 1
A pragmatic way would be to just ignore the non editable fields on the update statement.
I have actually circumvented this in the past by using a #ModelAttribute annotation and detecting the PK on the request, if you do it this way Spring will use the object that is returned from #ModelAttribute and automatically copy the submitted object to it.
It's kind of a hack and not obvious to someone who comes in to maintain the code though.
I have a form with a field for tags. Tags is a Doctrine ArrayCollection on the bound entity. The field is by_reference=false as the doc suggested, but binding the form to the entity behaves illegally while adding new element, like this:
$data=$entity->getTags(); //gets the ArrayCollection but does not care that it is not an array, and shoulrd be converted first
//do the value modifications like:
$data[]=new Tag(...);
$entity->setTags($data); //poor setter gets called with the already-updated collection, this operation is pointless
I figured that by_reference false was there to avoid this problem. If yes, then it's malfunctioning. If not, then the doc is very poor having an example for ArrayCollections but not caring about this very brutal neglection of setters...
What should I use instead? Returning a toArray() in getter is a no-go (obviouly it's not sane to design the model for compatibility with poor form implementation. Is there perhaps a type similar to 'collection' that forces conversion to array?
Add the tag to the entity as its supposed to happen:
$new_tag = new Tag(...);
$entity->addTag($new_tag);
There is no set-function for collections in a basic Doctrine generated entity.