How to create custom DbRefs in Spring Data - spring

I need to support a MongoDB database originally created by a parse.com installation.
I'm using Spring Boot and Spring Data. The problem is that parse.com and Spring Data have different implementations of DB references:
parse.com
_p_meal_ : { Meal$eh0662S2wn }
_p_FIELD_ : { <REF_CLASS>$<REF_ID> } // generically
Spring Data follows the recommendation
meal: { "$ref" : "meals", "$id" : ObjectId("5126bc054aed4daf9e2ab772"), "$db" : "maindb" }
FIELD: { "$ref": REF_CLASS, "$id": ID, "$db": DATABASE } // generically
I want to configure Spring Data so it knows how to read&write DB references the same way as parse.com.
I suspect it has to do with providing a custom DbRefResolver to MongoTemplate but I'm not sure.
Thanks

Related

Auditing in spring boot - How to custimise?

I followed this document for implementing Auditing in spring boot.
(https://www.baeldung.com/database-auditing-jpa)
Auditing is working fine but when the object is of type list means we are persisting as multiple entries in db.
I am passing this request object for rest API :-
`
[
{
"name": "reddy"
},
{
"name": "mani"
}
]
`
for each object we are getting one audit log in db.
Is there any way to achieve as single entry in database?

Publishing Avro messages using Kafka REST Proxy throws "Conversion of JSON to Avro failed"

I am trying to publish a message which has a union for one field as
{
"name": "somefield",
"type": [
"null",
{
"type": "array",
"items": {
"type": "record",
Publishing the message using the Kafka REST Proxy keeps throwing me the following error when somefield has an array populated.
{
"error_code": 42203,
"message": "Conversion of JSON to Avro failed: Failed to convert JSON to Avro: Expected start-union. Got START_ARRAY"
}
Same schema with somefield: null is working fine.
The Java classes are built in the Spring Boot project using the gradle plugin from the Avro schemas. When I use the generated Java classes and publish a message, with the array populated using the Spring KafkaTemplate, the message is getting published correctly with the correct schema. (The schema is taken from the generated Avro Specific Record) I copy the same json value and schema and publish via REST proxy, it fails with the above error.
I have these content types in the API call
accept:application/vnd.kafka.v2+json, application/vnd.kafka+json, application/json
content-type:application/vnd.kafka.avro.v2+json
What am I missing here? Any pointers to troubleshoot the issue is appreciated.
The messages I tested for were,
{
"somefield" : null
}
and
{
"somefield" : [
{"field1": "hello"}
]
}
However, it should be instead passed as,
{
"somefield" : {
"array": [
{"field1": "hello"}
]}
}

Aggregation of data on API Gateway

I am working on microservice architecture and I want to aggregate data from two microservices.
For example, Frontend calls the API Gateway and API Gateway calls two microservices Customer and Order microservices. Customer microservice returns customer details and Order microservice returns all ordered products by customer.
This is the format returned by API Gateway after aggregation from two microservice using Ocelot or Azure API Management.
Format 1
{
"Customers":[
{
"customerId":1001,
"customerName":"Tom"
},
{
"customerId":1002,
"customerName":"Jerry"
}
],
"Orders":[
{
"CustomerId":1001,
"Orders":[
{
"ProductId":"PRO1",
"ProductName":"Books"
},
{
"ProductId":"PRO2",
"ProductName":"Pens"
}
]
},
{
"CustomerId":1002,
"Orders":[
{
"ProductId":"PRO3",
"ProductName":"Pencils"
},
{
"ProductId":"PRO4",
"ProductName":"Toys"
}
]
}
]
}
The Format that I want is format 2.
Format 2
{
"OrderDetails":[
{
"customerId":1001,
"customerName":"Tom",
"Orders":[
{
"ProductId":"PRO1",
"ProductName":"Books"
},
{
"ProductId":"PRO2",
"ProductName":"Pens"
}
]
},
{
"customerId":1002,
"customerName":"Jerry",
"Orders":[
{
"ProductId":"PRO3",
"ProductName":"Pencils"
},
{
"ProductId":"PRO4",
"ProductName":"Toys"
}
]
}
]
}
The second format is achievable using Ocelot but the merging of data is based on the ids on Gateway and it requires some processing.
Is it a good practice to aggregate data on Gateway using business logic. If not what practices should be followed for this kind of aggregation?
It would be nice if you can provide some references for achieving this aggregation using the Azure API Management.
This is known as API composition or Backend for Frontend. I would say it is fine to aggregate data using the API Gateway because it allows your API clients to use a simpler API interface. The actual mapping would be done in the API Gateway.
However, when you chain multiple microservices together in one Web API, the failure of one service will cause the entire Web API to fail. An alternative (and more complex) solution is to create a dedicated microservice that aggregates the datasets from the other microservices and expose a single API that shows the joined data. See - CQRS pattern.
A reference for how you might implement this in Azure is API Aggregation Using Azure API Management.

Spring Cloud Config Server - Response Description

Is there any documentation which provides description of all the elements in Spring Cloud Config Server's response
{
"name":"myapp",
"profiles":[
"default"
],
"label":null,
"version":null,
"state":null,
"propertySources":[
{
"name":"vault:myapp",
"source":{
"foo":"myappsbar"
}
},
{
"name":"vault:application",
"source":{
"baz":"bam",
"foo":"bar"
}
}
]
}
Based on source code it's:
Simple plain text serializable encapsulation of a list of property sources. Basically a DTO for {#link org.springframework.core.env.Environment}, but also applicable outside the domain of a Spring application.
See: https://github.com/spring-cloud/spring-cloud-config/blob/master/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/environment/Environment.java
and
https://github.com/spring-cloud/spring-cloud-config/blob/master/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/environment/PropertySource.java
Please refer https://cloud.spring.io/spring-cloud-config/multi/multi__spring_cloud_config_server.html#vault-backend It has a response object which is the same as your question and the documentation can help you understand each and every parameter in that object.

Exchanging Spring Hypermedia Resources with HAL+JSON CURIEs via RestTemplate

I am using Spring Framework 4.1.0 and Spring HATEOAS 0.16.0 to develop both a Spring web application and a Spring test client for that application.
The test client has a statement like:
ResponseEntity<Resource<Calculation>> response = restTemplate.exchange(
calculationsUri,
HttpMethod.POST,
new HttpEntity<Calculation>(calculation),
new ParameterizedTypeReference<Resource<Calculation>>()
);
...wherein Calculation is a POJO with Jackson annotations (for example, #JsonProperty).
Without CURIEs, that RestTemplate.exchange() invocation succeeds: response.getBody().getLinks() returns a non-null non-empty instance of List<Link>.
My web application has non-standard link relations, for example, "sub-calculations". I want to use CURIEs.
With CURIEs, that RestTemplate.exchange() invocation fails: The response-deserialization code throws org.springframework.http.converter.HttpMessageNotReadableException, caused by com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException:
'Could not read JSON: Unrecognized field "name" (class org.springframework.hateoas.Link), not marked as ignorable (one known property "href"])'
In particular, Jackson fails to deserialize the CURIE(s) from the _links map in the response JSON to the List<Link>-typed field org.springframework.hateoas.ResourceSupport.links. The response JSON looks like:
{
"_links" : {
"self" : {
"href" : "..."
},
"myNamespace:sub-calculations" : [ {
"href" : "..."
}, {
"href" : "..."
} ],
"curies" : [ {
"href" : ".../{rel}",
"name" : "myNamespace",
"templated" : true
} ]
}
}
How may I use RestTemplate.exchange() to obtain a resource whose HAL+JSON ("application/hal+json") representation uses CURIEs?
looks like the library simply doesn't support the name field of HAL link object https://datatracker.ietf.org/doc/html/draft-kelly-json-hal-06#section-5.5 ...doesn't really have anything to do with CURIE's. You should open an issue with that library to support all the fields of HAL link objects.
As far as CURIE #CCCV in your example they key is AWALYS myNamespace:sub-calculations no matter if CURIE is present or not. CURIE just lets you dereference to a URL that SHOULD link to documentation. It's kinda weird, and i see implementations get it wrong all the time thinking the URI is what matters. see https://groups.google.com/d/msg/hal-discuss/lt0CnC3eev4/YinN1Us54KcJ i'm not saying i agree with it..but that's how it's supposed to be

Resources