Spring data mongodb federation attempts -- how can I get interface methods to use a custom configured mongotemplate? - mongodb

In my application, I need to be able to connect to any number of mongodb hosts, and any number of databases in any of those hosts to support at least this basic level of query federation. This is specified by configuration, so, for any given installation of our app, I cannot know ahead of time how many collections I will need to access. I based my attempt on configuration that I saw in this Baeldung article with some modifications to suit my requirements. My configuration looks something like this yaml:
datasources:
- name: source1
uri: mongodb://user1:pass1#127.0.0.1:27017
fq_collection: db1.coll1
- name: source2
uri: mongodb://user1:pass1#192.168.0.100:27017
fq_collection: db2.coll2
And, depending on the installation, there could be any number of datasources entries. So, in my #Configuration class, I can iterate through these entries that are injected via configuration properties. But I want to create a MongoTemplate that I can set up for each of these, since I cannot rely on the default MongoTemplate. The solution that I have attempted is to create a repository interface, and then to create a custom impl that will accept the configured MongoTemplate. When I use this code to create each Repository instance with its template:
public MongoRepository<String, Item> mongoCustomRepositories(MongoTemplate template) {
MyCustomMongoRepository customImpl = new MyCustomMongoRepositoryImpl(template);
MongoRepositoryFactory repositoryFactory = new MongoRepositoryFactory(template);
return repositoryFactory.getRepository(MyMongoRepository.class, customImpl);
}
And I call it from a #Bean method that returns the list of all of these repositories created from the config entries, I can inject the repositories into service classes.
UPDATE/EDIT: Ok, I set mongodb profiling to 2 in order to log the queries. It turns out that, in fact, the queries are being sent to mongodb, but the problem is that the collection names are not being set for the model. I can't believe that I forgot about this, but I did, so it was using the lower camel case model class name, which will make sure that there are no documents to be retrieved. I have default collection names, but the specific collection names are set in the configuration, like the example YAML shows. I have a couple of ideas, but if anyone has a suggestion about how to set these dynamically, then that would help a lot.
EDIT 2: I did a bunch of work and I have it almost working. You can see my work in my repo. However, in doing this, I uncovered a bug in spring-data-mongodb, and I filed an issue.

Related

REST new ID with DDD Aggregate

This question seemed fool at first sight for me, but then I realized that I don't have a proper answer yet, and interestingly also didn't find good explanation about it in my searches.
I'm new to Domain Driven Design concepts, so, even if the question is basic, feel free to add any considerations to it.
I'm designing in Rest API to configure Server Instances, and I came up with a Aggregate called Instance that contains a List of Configurations, only one specific Configuration will be active at a given time.
To add a Configuration, one would call an endpoint POST /instances/{id}/configurations with the body on the desired configuration. In response, if all okay, it would receive a HTTP 204 with a Header Location containing the new Configuration ID.
I'm planning to have only one Controller, InstanceController, that would call InstanceService that would manipulate the Instance Aggregate and then store to the Repo.
Since the ID's are generated by the repository, If I call Instance.addConfiguration and then InstanceRepository.store, how would I get the ID of the newly created configuration? I mean, it's a List, so It's not trivial as calling Instance.configuration.identity
A option would implement a method in Instance like, getLastAddedConfiguration, but this seems really brittle.
What is the general approach in this situation?
the ID's are generated by the repository
You could remove this extra complexity. Since Configuration is an entity of the Instance aggregate, its Id only needs to be unique inside the aggregate, not across the whole application. Therefore, the easiest is that the Aggregate assigns the ConfigurationId in the Instance.addConfiguration method (as the aggregate can easily ensure the uniqueness of the new Id). This method can return the new ConfigurationId (or the whole object with the Id if necessary).
What is the general approach in this situation?
I'm not sure about the general approach, but in my opinion, the sooner you create the Ids the better. For Aggregates, you'd create the Id before storing it (maybe a GUID), for entities, the Aggregate can create it the moment of creating/adding the entity. This allows you to perform other actions (eg publishing an event) using these Ids without having to store and retrieve the Ids from the DB, which will necessarily have an impact on how you implement and use your repositories and this is not ideal.

Strapi: Initialize / populate database

When I deploy Strapi to a new server, I want to create and populate the database tables (PostgreSQL), particularly categories. How do I access production config, and create tables and category entries?
A hint on how-to approach this, would be much appreciated!
I know this is an old question, but i recently came upon the same issue.
Basically you should create the collections first, which result in the creation of models. Of course you also could create the models manually.
In the recent documentation you find a section about a bootstrap function.
docs bootstrap
The function is called at the start of the server.
The docs list the following use cases:
Here are some use cases:
Create an admin user if there isn't one.
Fill the database with some necessary data.
Load some environment variables.
The bootstrap function can be synchronous or asynchronous.
A great example can be found in the Plugin strapi-plugin-users-permissions
You can implement a new service or overwrite a function of an existing plugin.
the function initialize is implemented here async initialize
and called in the bootstrap function here
await ...initialize()
The initialize function is used to populate the database with the two roles
Authenticated and Public.
Hope that helps whoever stumbles upon this question.

How do I disable GridFS MD5 calculation in Spring Boot?

Now that the md5 attribute of GridFS files collection is obsolete, drivers are not required to compute it, so I'd like to disable it to spare a few milliseconds maybe...
The MongoDB Java driver does provide an option disableMD5 in GridFSBucketImpl, but since I'm using Spring Boot's GridFsTemplate (spring-data-mongodb 2.1.2.RELEASE) I don't have direct access to it. GridFsTemplate has a method getGridFs() that returns a GridFSBucket configured for the current database and bucket name, but unfortunately this method is private so I can't override it.
So what are my options? Do I have to override all of GridFsTemplate? Did I miss a simple setting somewhere? Should I submit a feature request to Spring?
Update
Obviously GridFsTemplate is not meant to be extended (though all it would take is getGridFs and a couple fields to be protected) so I ended up creating my own CustomGridFsTemplate, which is an almost exact copy of GridFsTemplate except that I call GridFSBucket.withDisableMD5(true) in getGridFs.
I'm not very happy with that, but it works and I don't see a better option for now.
Update 2
I have submitted a Spring feature request, please vote for it! https://jira.spring.io/browse/DATAMONGO-2165
There's currently no better way. Looks like you filed a ticket to extend GridFsTemplate to allow the customizations.

Row level security using prisma and postgres

I am using prisma and yoga graphql servers with a postgres DB.
I want to implement authorization for my graphql queries. I saw solutions like graphql-shield that solve column level security nicely - meaning I can define a permission and according to it block or allow a specific table or column of data (on in graphql terms, block a whole entity or a specific field).
The part I am stuck on is row level security - filtering rows by the data they contain - say I want to allow a logged in user to view only the data that is related to him, so depending on the value in a user_id column I would allow or block access to that row (the logged in user is one example, but there are other usecases in this genre).
This type of security requires running a query to check which rows the current user has access to and I can't find a way (that is not horrible) to implement this with prisma.
If I was working without prisma, I would implement this in the level of each resolver but since I am forwarding my queries to prisma I do not control the internal resolvers on a nested query.
But I do want to work with prisma, so one idea we had was handling this in the DB level using postgres policy. This could work as follows:
Every query we run will be surrounded with “begin transaction” and “commit transaction”
Before the query I want to run “set local context.user_id to 5"
Then I want to run the query (and the policy will filter results according to the current_setting(‘context.user_id’))
For this to work I would need prisma to allow me to either add pre/post queries to each query that runs or let me set a context for the db.
But these options are not available in prisma.
Any ideas?
You can use prisma-client instead of prisma-binding.
With prisma-binding, you define the top level resolver, then delegates to prisma for all the nesting.
On the other hand, prisma-client only returns scalar values of a type, and you need to define the resolvers for the relations. Which means you have complete control on what you return, even for nested queries. (See the documentation for an example)
I would suggest you use prisma-client to apply your security filters on the fields.
With the approach you're looking to take, I'd definitely recommend a look at Graphile. It approaches row-level security essentially the same way that you're thinking of. Unfortunately, it seems like Prisma doesn't help you move away from writing traditional REST-style controller methods in this regard.

Hibernate Search: Get all fields for faceting

I want to place facet requests to (some) indexed fields. In order to place a facet request, I need to know the name of the corresponding field.
Is there a way to programmatically get a list of field names annotated with #Field?
The answer to your question will depend on the version of Search you are using. If you are using a pre Search 5 release where it was possible to facet on any #Field (with the documented restrictions), then you can use the public metadata API to get all configured fields.
The entry point into the public metadata API is via SearchFactory.getIndexedTypeDescriptor(Class<?> entityType) which returns an IndexedTypeDescriptor for the specified entity type. You can then iterate the configured properties and for each properties get the list of configured fields.
As of Search 5, however, facet fields needs to be marked at configuration time using #Facet(s). Only properties with this annotation can be faceted upon. Obviously the public metadata API should expose this as well. Unfortunately, this is not yet implemented - HSEARCH-1853.
There is a workaround if you are happy to use some internal APIs which might change in the future. You would only need this until HSEARCH-1853 is implemented at which stage you could switch to this public (and supported) API.
Search also maintains something which is called an internal metadata API which it uses for all its inner workings. It is basically just a richer model of the public API which is more restrictive on what's exposed. Bottom lines, you want to get hold of the org.hibernate.search.engine.metadata.impl.FacetMetadata. To do so you need to get hold of the DocumentBuilderIndexedEntity which gives you access to the internal org.hibernate.search.engine.metadata.impl.TypeMetadata. Via this type metadata you can get access to PropertyMetadata, then DocumentFieldMetadata and finally FacetMetadata.
To get hold of the DocumentBuilderIndexedEntity, you could do something like this:
ExtendedSearchIntegrator integrator = ContextHelper.getSearchintegratorBySFI( sessionFactory );
IndexManager[] indexManagers = integrator.getIndexBinding( clazz ).getIndexManagers();
DirectoryBasedIndexManager indexManager = (DirectoryBasedIndexManager) indexManagers[0];
EntityIndexBinding indexBinding = indexManager.getIndexBinding(clazz);
DocumentBuilderIndexedEntity documentBuilder = indexBinding.getDocumentBuilder();
Note, the internal API might change at any stage. No guarantees regarding backwards compatibility and evolution of the API are given.