How to create custom schema with Corda Vault Extension - database-schema

From Corda documents, it says we can have custom schema in Vault Extension.
However there is not much clarity for Vault Extension which should have ability to create/manage custom database schema pertaining to node vault database.
Are we going to publish API in feature release of Corda

Inside flows, the node exposes a JDBC connection that allows you to write native custom SQL queries (as a vault extension). You can access this JDBC connection using serviceHub.jdbcSession().
If your question is about how to write a custom schema then please see the existing Corda Persistence API docs.
You can then query that custom schema using the new Vault Query API - please see the existing [Corda Vault Query API][3] docs.

Just to add an example to the above, here's a custom schema for the Yo! CorDapp. See YoSchemaV1 below:
// State.
data class State(val origin: Party,
val target: Party,
val yo: String = "Yo!") : ContractState, QueryableState {
override val participants get() = listOf(target)
override val contract get() = Yo()
override fun toString() = "${origin.name}: $yo"
override fun supportedSchemas() = listOf(YoSchemaV1)
override fun generateMappedObject(schema: MappedSchema) = YoSchemaV1.YoEntity(this)
object YoSchemaV1 : MappedSchema(Yo.State::class.java, 1, listOf(YoEntity::class.java)) {
#Entity #Table(name = "yos")
class YoEntity(yo: State) : PersistentState() {
#Column var origin: String = yo.origin.name.toString()
#Column var target: String = yo.target.name.toString()
#Column var yo: String = yo.yo
}
}
}
In short, your state object needs to implement QueryableState, as above.
The full CorDapp is available here: https://github.com/roger3cev/yo-cordapp
Cheers

Related

How to import a schema.prisma file inside another?

One of my schema.prisma's file is wrote like this:
generator client {
provider = "prisma-client-js"
output = "./generated/own_database"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model Employee {
...
}
And I have another one, which is like this:
generator client {
provider = "prisma-client-js"
output = "./generated/another_database"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL_2")
}
model Costs {
cod_center_cost Int #id
description String? #db.VarChar(100)
status Boolean?
classification Int?
}
...
I have a model that needs to have a relation to another model, but how can I refer an another file's model?
Splitting Prisma's schema file is not officially possible yet.
However there are some community provided solutions like Aurora which provides you functionality to split prisma schemas and import them.
Here's the Official GitHub Issue where splitting schema file is being tracked by Prisma Team.

How to expose additional models : Migrating from Springfox to Springdoc

I need to expose some models which don't used directly in REST API methods.
With springfox I used Docket's additionalModels method to programmatically add models to specification:
docket.additionalModels(
typeResolver.resolve(XModel1.class),
typeResolver.resolve(XModel2.class)
)
How to do it with springdoc?
I've created a dummy operation with dummy-parameter which includes all required models. But I feel the approach has space for improvement.
With OpenApiCustomiser , you have access to the OpenAPI Object.
You can add any object/operation you want without having to add annotations on your code.
You can have a look at the documentation for more details:
https://springdoc.org/#how-can-i-customise-the-openapi-object
In Kotlin
fun components(): Components {
val components = Components()
val converter = ModelConverters.getInstance()
val schema1 = converter.readAllAsResolvedSchema(XModel1::class.java)
val schema2 = converter.readAllAsResolvedSchema(XModel2::class.java)
schema1.referencedSchemas.forEach { s -> components.addSchemas(s.key, s.value) }
schema2.referencedSchemas.forEach { s -> components.addSchemas(s.key, s.value) }
return components
}
Additionally you may need to specify the property in application.yml:
springdoc:
remove-broken-reference-definitions: false

Using requestContinuation to make pagination in Spring-Data-CosmosDB

I'm using spring-data-cosmosdb 2.2.2 with azure-cosmos 3.6.0 and Scala.
I'm using CosmosTemplate to create custom DocumentQueries using sorting and pagination.
My problem is to navigate through the pages in my request using requestContinuation. Every request (POST) is returning a requestContinuation like that:
"requestContinuation": "{\"compositeToken\":\"{\\"token\\":null,\\"range\\":\\"{\\\\"min\\\\":\\\\"05C1DFFFFFFFFC\\\\",\\\\"max\\\\":\\\\"FF\\\\",\\\\"isMinInclusive\\\\":true,\\\\"isMaxInclusive\\\\":false}\\"}\",\"orderByItems\":[{\"item\":\"8b90e589-09d8-42e7-a3e2-d26cf2c38a63\",\"map\":{\"item\":\"8b90e589-09d8-42e7-a3e2-d26cf2c38a63\"}}],\"rid\":\"I9lLALNXyUNECgEAAAAACA==\",\"inclusive\":true}"
The first thing I saw is the inner "token" is always null.
I tried to copy the whole string and put it on my request as parameter but it didn't work:
POST https://baseurl/api/documents/recent?page=1&requestContinuation=...
The requestContinuation never changes and the documents returned in the page are always the same. I'm using Postman and Insomnia.
I don't find good examples to use requestContinuation.
Am I missing something? Maybe encoding the token with base64?
I don't know if the problem is just to pass the requestContinuation or if there's something wrong in my code.
In resume I'm just using paginationQuery method to execute a documentQuery with some criterias and a "pageable" object.
My Controller:
#RestController
#RequestMapping(path = Array("/api"))
class DocumentController(#Autowired private val service: DocumentService) extends BaseController {
#PostMapping(path = Array("/documents/recent"), produces = Array("application/json"))
def findRecentDocuments(pageable: Pageable,
#RequestBody params: DocumentParams,
#RequestHeader(name="apiKey") token: String
): Page[Document] = {
service.findRecentDocuments(pageable, Option(params))
}
My service:
class DocumentService(#Autowired private val documentRepository: DocumentRepository, #Autowired private val template: CosmosTemplate) extends BaseService {
def findRecentDocuments(pageable: Pageable, params: Option[DocumentParams]): Page[Document] = {
val documentClass = classOf[Document]
val collectionName = template.getCollectionName(documentClass)
val defaultSort = Sort.by(Direction.ASC, "id")
val sort = pageable.getSortOr(defaultSort)
val criteria = QueryUtils.getCriteria(params, documentClass)
getCriteriaInfo(criteria)
documentRepository.findRecentDocuments(pageable, criteria, sort, documentClass, collectionName)
}
My repo:
class DocumentRepository(#Autowired private val template: CosmosTemplate) {
def findRecentDocuments(pageable: Pageable, criteria: Criteria, sort: Sort, documentClass: Class[Document], collectionName: String): Page[Document] = {
val query = new DocumentQuery(criteria)
template.paginationQuery(query.`with`(sort).`with`(pageable), documentClass, collectionName)
}
}
Thanks for any help.
Did you try the recommended way of pagination provided in the readme section of spring-data-cosmosdb: https://github.com/microsoft/spring-data-cosmosdb/blob/master/README.md
Section: Supports Spring Data pageable and sort.
Also documented here: https://learn.microsoft.com/en-us/azure/java/spring-framework/how-to-guides-spring-data-cosmosdb#pagination-and-sorting
As I already commented in the original issue on MS Github I found the solution changing the "Pageable" object to "CosmosPageRequest" object which uses requestContinuation.
This worked for me.
Here's the code:
https://github.com/microsoft/spring-data-cosmosdb/issues/484
Thanks.
Lucas Porto, If you open to using the Java SDK, I have implemented infinite scroll with reactive Java SDK 4.0.
The "next" method in the following controller class is the server side entry point for the pagination used by the jQuery Ajax call.
Code on GitHub

Any way I can change in runtime mongo document name

In the project we need to change collection name suffix everyday based on date.
So one day collection is named:
samples_22032019
and in the next day it is
samples_23032019
Everyday I need to change suffix and recompile spring-boot application because of this. Is there any way I can change this so the collection/table can be calculated dynamically based on current date? Any advice for MongoRepository?
Considering the below is your bean. you can use #Document annotation with spring expression language to resolve suffix at runtime. Like show below,
#Document(collection = "samples_#{T(com.yourpackage.Utility).getDateSuffix()}")
public class Samples {
private String id;
private String name;
}
Now have your date change function in a Utility method which spring can resolve at runtime. SpEL is handy in such scenarios.
package com.yourpackage;
public class Utility {
public static final String getDateSuffix() {
//Add your real logic here, below is for representational purpose only.
return DateTime.now().toDate().toString();;
}
}
HTH!
Make a cron job to run daily and generateNewName for your collection and execute the below code. Here I am getting collection using MongoDatabse than by using MongoNamespace we can rename the collection.
To get old/new collection name you can write a separate method.
#Component
public class RenameCollectionTask {
#Scheduled(cron = "${cron}")
public void renameCollection() {
// creating mongo client object
final MongoClient client = new MongoClient(HOST_NAME, PORT);
// selecting the mongo database
final MongoDatabase database = client.getDatabase("databaseName");
// selecting the mongo collection
final MongoCollection<Document> collection = database.getCollection("oldCollectionName");
// creating namespace
final MongoNamespace newName = new MongoNamespace("databaseName", "newCollectionName");
// renaming the collection
collection.renameCollection(newName);
System.out.println("Collection has been renamed");
// closing the client
client.close();
}
}
To assign the name of the collection you can refer this so that every time restart will not be required.
The renameCollection() method has the following limitations:
1) It cannot move a collection between databases.
2) It is not supported on sharded collections.
3) You cannot rename the views.
Refer this for detail.

Azure Service Fabric and Azure Key Vault Secret Error

I am getting the following when trying to implement Azure Key Vault Secret from a stateless service fabric works just fine from a console app.
System.TypeLoadException
HResult=0x80131522
Message=Inheritance security rules violated by type: 'System.Net.Http.WebRequestHandler'. Derived types must either match the security accessibility of the base type or be less accessible.
Source=Microsoft.Rest.ClientRuntime
StackTrace:
at Microsoft.Rest.ServiceClient`1.CreateRootHandler
public async Task<string> GetAccessToken(string authority, string resource, string scope)
{
var clientId = MyConfig.Settings.Sections["MyConfigSection"].Parameters["AuthClientId"].Value;
var clientSecret = MyConfig.Settings.Sections["MyConfigSection"].Parameters["AuthClientSecret"].Value;
ClientCredential clientCredential = new ClientCredential(clientId, clientSecret);
var context = new AuthenticationContext(authority, TokenCache.DefaultShared);
var result = await context.AcquireTokenAsync(resource, clientCredential);
return result.AccessToken;
}
public string GetCRMConnectionString()
{
var secretvaultAddress = MyConfig.Settings.Sections["MyConfigSection"].Parameters["SecretVaultUrl"].Value;
var client = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(GetAccessToken));
return client.GetSecretAsync(secretvaultAddress).GetAwaiter().GetResult().Value;
}
WebRequestHandler type(whose instance gets created in your case) is a part of System.Net.Http.WebRequest.dll. If you explore assembly's attributes, you'll find the next one applied to it -
[assembly: AllowPartiallyTrustedCallers]
This attribute makes the assembly being considered as SecurityTransparent. WebRequestHandler is derived from HttpClientHandler defined in another assembly - System.Net.Http.dll. So probably on the environment where you have the code deployed, System.Net.Http.dll is missing AllowPartiallyTrustedCallers which makes it security-critical, meaning that rules get violated - transparent code can not call into security-critical one.
Try to resolve it by either creating a binding rule to a specific System.Net.Http.dll version that has AllowPartiallyTrustedCallers attribute or try to create HttpClient explicitly and pass it then into KeyVaultClient ctr.
Refer to this link for more details and options - Inheritance security rules violated by type: 'System.Net.Http.WebRequestHandler'.