What does Spring Data Couchbase use the _class field for? - spring

I'm guessing that the type is used for CRUD operations. Is it used for anything else besides that? I'm wondering what impact there could be from configuring how it gets populated.

The _class field is written to allow polymorphic properties in your domain model. See this sample:
class Wrapper {
Object inner;
}
Wrapper wrapper = new Wrapper();
wrapper.inner = new Foo();
couchbaseOperations.save(wrapper);
You see how the field inner will get Foo serialized and persisted. On the reading side of things we now have to find out which type to create an object of and the type information in Wrapper is not enough to do so as it only states Object.
That's why Spring Data object mapping persists an additional field (name customizable but defaulting to _class) to store that information to be able to inspect the source document, derive a type from the value written for that field and eventually map that document back to that particular type.
The Spring Data Couchbase reference documentation doesn't really document it, you can find information about the way this works in the docs for the MongoDB module. I've also created a ticket for Spring Data Couchbase to improve on the docs for that.

Related

Model derivative fetch properties for object id(s)

We have some big models where we need to read properties via the model derivative api. Reading all properties leads to an out of memory of the heap. We need to check the properties of each object for a custom prop set in a cad program like revit or navisworks.
So we are exploring to fetch properties for an object, explained here:
https://forge.autodesk.com/blog/new-objectid-query-parameter-model-derivative-properties-api
But after reading the metadata for the guid, we have like 50k of objectids or more. Thats too much to fetch the properties separately per object.
Is there a possibility to:
- fetch properties for multiple object id's?
- Fetch the properties for an object id and all his children?
Or is there another recommendation on how to handle such big models where the response when reading all the properties is too big (and we don't know up front which objectIds to read properties from)?
kind regards
I completely understood your question and as I know you working with .nwm format which is basically includes all the files from project (this is the reason for such amount objects in metadata)
For such case you can use middle-ware server with custom helpers methods, please take a look on this repo from Cyrille Fauvel,
https://github.com/cyrillef/propertyServer
It can help you working with multiple id, with range of id's, some methods you can take as base for your own.
Also, as far as I understood you getting property programatically so maybe you can some how use 'name' field in metadata object which is also can be unique as 'guid'.

Read null as empty set in springdata-cassandra

I use spring-data-cassandra, and have entity like this:
#Table("users")
public class User {
#Column("permissions")
#CassandraType(type = DataType.Name.SET, typeArguments = {DataType.Name.TEXT})
public Set<String> permissions = new HashSet<>();
}
In cassandra I have table users with field permissions of type Set. It works fine when I store some values in the set, but when I try to store empty set, it becomes null when I read such entity from the repository.
Is there a way to force spring-data-cassandra to change null to empty HashSet? Or can I somehow add custom reader for this specific property of the entity?
TL;DR;
That's Cassandra's default behavior to return null for empty Collection and Map-typed columns.
Further Read
Cassandra returns null values for lists, sets, and maps, which do not contain any items. This is especially unfortunate when using classes with pre-initialized fields as seen in your question. There's an open ticket (DATACASS-266 - Loading empty collection-typed properties overwrites pre-initialized fields) in the issue tracker - as of now, without comments or votes.
We're not exactly sure whether it's a good idea to skip setting properties or apply some sort of defaulting when dealing with empty (null) collections as this raises follow-up questions what to do when:
Creating an instance through constructor creation: A value is required in such case. For property access, we could omit to set the property, for constructor creation we must provide a value.
The pre-initialized collection contains items but the one received from Cassandra is null.
We assume, the change would be applied, what will happen with already existing code that assumes empty collections default to null.
A possibility to address this behavior could be configuration on MappingCassandraConverter or an extension point to override so users can apply their own empty collection behavior.
I've been trying to eliminate the null collections in my model objects as well, and while it may not be possible to do that at the Spring Data level currently (version 2.1.x), there are some options you can consider:
Use property access for the field in question (i.e. use the annotation #AccessType(PROPERTY)), and in the setter method, set the field to an empty collection when the argument is null.
Define a compatible (see below) constructor that sets the field to an empty collection when a null is provided (and if the model is mutable, you may still want to provide the setter as above).
There are some caveats to ensure Spring Data Cassandra uses the desired constructor (e.g. don't provide a no argument constructor), so it's critical to review the "Object Mapping Fundamentals" section of the reference guide (https://docs.spring.io/spring-data/cassandra/docs/current/reference/html/#mapping.fundamentals).
Among the recommendations in that reference guide (as of version 2.1 at least) is to use an all argument constructor and make model objects immutable, which would work well with the constructor-based approach to handling nulls. Though it does mean writing and maintaining the constructor to handle the nulls rather than relying on Lombok's #AllArgsConstructor.
I have used the property access approach in one case, but not the constructor approach. However I do intend go the constructor route when adding new or model classes (I'm a fan of immutable objects, and will explore that route even without any collection fields)
I believe Spring Data Cassandra 2.0 also added persistence lifecycle callbacks which is another possible option I suppose, but I ruled that out, mainly because the logic would not reside in the model class itself (as well as going against the recommendations from the creators of the framework)

Creating a capped collection using Spring data MongoDB #Document

I am trying out reactive support in spring-data with MongoDB. I am using spring-boot 2.0.0.
Generally I would write a domain object like this in my project:
#Document
public class PriceData {
......
}
With this spring-data it would create a collection with name priceData in MongoDB. If I want to customize it, then I would do it using the collection attribute:
#Document(collection = "MyPriceData")
Since I want to try reactive support of MongoDB, I want to create a capped collection so that I can use #Tailable cursor queries.
I can create a capped collection in my MongoDB database as specified here:
CollectionOptions options = new CollectionOptions(null, 50, true);
mongoOperations.createCollection("myCollection", options);
or
db.runCommand({ convertToCapped: 'MyPriceData', size: 9128 })
This is not a big problem if I use some external MongoDB database where I can just run this command once. But if I use an embedded MongoDB, then I would have put this in a class which would be executed every time during start up.
Either way I would be creating a collection even before the first request. So I was wondering if there is a way, I could specify to spring-data-mongodb that I need a capped collection instead of regular collection.
Unfortunately #Document doesn't help in this case.
So below is from Oliver
Might be a good idea to have those options exposed to the #Document annotation to automatically take care of them when building the mapping context but we generally got the feedback of people wanting to manually handle those collection setup and indexing operations without too much automagic behavior. Feel free to open a JIRA in case you'd like to see that supported nevertheless.
This is back in 2011. And it seems its still true to date. If you really need the change to handle it using annotation, you should open a JIRA ticket

MongoDB type inference using _class

I've been reading the MongoDB documentation and Spring adds a _class field by default to the stored data. Is there any way to use this information to have type inference?
For example: There is a an abstract class Animal with three subclasses Dog, Cat, Bird. Say you have a class Zoo which contains a list of animals. In the database you store those Zoo Objects. Is there any function to get a List<Animal> back with Animals that can be upcasted?
I'm using Spring so I prefer to have a solution that would work using the spring-data-mongodb. But an external mapping library would be fine too. I prefer not to write it myself as it seems basic mapping functionality.
Make sure you map all types you mentioned to be stored in the same collection (e.g. using the #Document annotation). Then you can simply execute queries against the collection handing in Animal to the according method on MongoTemplate. The underlying converter will then automatically instantiate the correct types based on the information stored in _class. The same applies to the usage of Spring Data MongoDB repositories.

grails - I need to define my validation at runtime

I have an idea to read an XML document from the database and generate simple CRUD screens (via Grails) based on the data defined. My application will call RESTFul services to persist the data so I don't need Hibernate on the client side. I have ideas about how to generate the UI but where I'm stumped is in how to perform the validation.
I'll have a single, generic domain/command object that contains only the fields that are common for all instances of this "runtime" data type. All other fields are defined via the XML found in the database. I need something like this:
String xml // defines the fields, constraints, UI information for this data type
def constraints = {
callMyCustomValidator(obj)
}
and in my callMyCustomValidator method, I'll extract the xml for obj and perform my validation as needed.
Note: We have a working example of this in a different app (written in java/servlers/jsp) and without any formal "framework" this isn't difficult to do. Why do I need this? We need to add simple datatypes on the fly (via script) without a release.
You can use the validator to add custom validation to your domain class. Just add this to some of your common fields.

Resources