How to validate only the JSON signature(Not Values) returned by Micro Service using Spring Cloud Contract - spring-cloud-contract

I have a groovy script where i am trying to validate the JSON attributes in a method in the base test class(assertDepartment).
import org.springframework.cloud.contract.spec.Contract
Contract.make {
request {
method 'GET'
url '/dept-service/12345'
}
response {
status 200
headers {
header 'Content-Type': 'application/json;charset=UTF-8'
}
body ($(consumer('dept.json'), producer(execute('assertDepartment($it)'))))
}
}
dept.json
[{
"departmentList": [
{
"dept_code": "12345",
"dept_name": "AAA",
"desc": "aaa",
},
{
"dept_code": "12345",
"dept_name": "BBB",
"desc": "bbb",
}
]
}]
From the Publisher point of view, it is all good, but the stubs are including the JSON with values as is, per the dept.json above.
From the Consumer point of view, i would like to verify only the signature of the JSON, but not by values, as i am connecting to a different database.
Here the JSON comparison is STRICT with respect to values.
How can i send the generic JSON format to Consumer and how can i restrict only attribute checking(like dept_code, dept_name, desc ) not the values (AAA, aaa, BBB, bbb)
Please help.

After going through the documentation, i have realized the below with respect to Spring Cloud Contract implementation.
- Spring Cloud Contract Request/Responses are Static, Not Dynamic
We have to have specific static request/response data for each case/scenario
Producer can not switch it to real time, and can not dynamically change the input and expect the Consumer to have the same output
Spring Cloud Contract Producer JSON Responses are Static as the Consumer is going to compare with the same forever
If Producer is going to provide a JSON Response based on an Account with multiple possible combination of datasets, then the Consumer also should invoke the Service via the Stubs with the same Account input, otherwise it is going to Fail
Consumer is not going to Connect to any Database, but just compares the JSON in the Stubs against the Hard-coded response at Consumer end.
Nice to Have
Producer/Consumer should be able to Connect to either same or different databases and switch the Request input dynamically, which makes the Integration Testing using Spring Cloud Contract More Robust.
Case:
Consider a Bank Account with Joint Account Holder information.
Producer exposes a Micro Service which gives Account information to the Consumer.
Today, Mr. Bob has an Account without any Joint Account holder information.
Producer generates the Stubs and communicates the same with 10 Consumers.
Tomorrow, Mr. Bob wants to Add his spouse Ms. Lily as a Joint Account Holder.
Now, Producer generates the Stubs and communicates the same with 10 Consumers.
Out of which 3 Consumers do not need Joint Account information, but 7 of them are strictly dependent on the complete information.
Firstly, All the 10 Consumers will have to re-write the Test cases from their end, as the Integration Test is going to Fail, because it returns an Additional information but as the Consumers are statically comparing the response with the hard-coded value/signature.

Related

Confused about health checking protocol

I have read below doc, source code and issue:
https://github.com/grpc/grpc/blob/master/doc/health-checking.md
https://github.com/grpc/grpc-node/blob/master/packages/grpc-health-check/test/health_test.js
https://github.com/grpc/grpc/issues/10428
I provide an example and try to explain:
// Import package
let health = require('grpc-health-check');
// Define service status map. Key is the service name, value is the corresponding status.
// By convention, the empty string "" key represents that status of the entire server.
const statusMap = {
"ServiceFoo": proto.grpc.health.v1.HealthCheckResponse.ServingStatus.SERVING,
"ServiceBar": proto.grpc.health.v1.HealthCheckResponse.ServingStatus.NOT_SERVING,
"": proto.grpc.health.v1.HealthCheckResponse.ServingStatus.NOT_SERVING,
};
// Construct the service implementation
let healthImpl = new health.Implementation(statusMap);
// Add the service and implementation to your pre-existing gRPC-node server
server.addService(health.service, healthImpl);
I am not clear about the following points:
Does the service name in statusMap need to be the same as the service name in the protocol buffers file? Or the service name can be arbitrarily specified. If so, how does the service name map to the service defined in the protocol buffers?
From the health checking protocol:
The server should register all the services manually and set the individual status
Why do we need to register manually? If the service code can be generated, why doesn't grpc help us automatically register the service name in statusMap? (Imagine setting the status of 100 services one by one)
The service status is hard code and cannot be changed at application runtime. If my service is unavailable at runtime for some reason such as misconfiguration, downstream service is not available, but the status of the service is always serving(because it's hard code), if so, what is the meaning of the health check?
For RESTful API, we can provide a /health-check or /ping API to check that the entire server is running normally.
Regarding the service names, the first linked document says this:
The suggested format of service name is package_names.ServiceName, such as grpc.health.v1.Health.
This does correspond to the package names and service name defined in the Protobuf definition.
The services need to be registered "manually" because the status is determined at the application level, which the grpc library does not know about, and a registered service name is only meaningful along with the corresponding status. In addition, the naming format mentioned above is just a convention; the health check service user is not constrained to it, and the actual services on the server are not constrained to use the standard /package_names.ServiceName/MethodName method naming scheme either.
Regarding the third point, the service status should not be hardcoded, and can be changed at runtime. The HealthImplementation class used in the code in the question has a setStatus method that can be used to update the status.
Also, as mentioned in a comment in the code in the question,
By convention, the empty string "" key represents that status of the entire server.
That can be used as the equivalent of the /health-check or /ping REST APIs.

Corda 4 - Querying vault by specific transactionid

We are building a POC using Corda 4 and Springboot web server.
We are currently using the following code to retrieve all the states from the vault via RPC -
val vaultStatesAndRefs = services.proxy.vaultQueryBy<State>().states
val vaultStates = vaultStatesAndRefs.map { it.state.data }
We want - to retrieve a state from the vault via RPC using the transactionId.
Kindly guide in achieving this.
Please note that Corda doesn't guarantee the set of transactions retrieved via any method would remain consistent across future versions of Corda. This is because the future version of Corda would use SGX-encrypted format to exchange transaction chain between nodes. Thus the transactions can only be decrypted in a secure SGX enclave.
Having said that there is no direct API exposed which could be used to obtain state based on transactionId via RPC. The one you could use (internalFindVerifiedTransaction) have been deprecated and would likely be removed in the future versions of Corda.
The way to do this I suppose would be to use flow. You could retrieve the output states based on the transactionId.
SignedTransaction tx = getServiceHub().getValidatedTransactions().getTransaction(
SecureHash.parse(txId));
tx.toLedgerTransaction(getServiceHub()).getOutputStates();
You could then trigger the flow from your client using RPC and get the result from the FlowHandle object returned.
FlowHandle<List<ContractState>> flowHandle =
proxy.startFlowDynamic(GetStateFlow.class, txId);
List<ContractState> list = flowHandle.getReturnValue().get();

Redux - Where to keep non-serializable Data?

Suppose, i want to keep some non-serializable data for my applciation, which the user can access and interact with across the application. So for example, a connected device (bluetooth, wlan), a media stream, something of this sort. Im wondering where to put such data, when using the Redux paradigm?
Pseudocode:
A normal lifecycle of a subscription might look like this:
Subscription connection = instance.connect(device, request).listen();
...
connection.send(data);
...
data = connection.read();
...
connection.unsubscribe();
the app store might look like this:
Store:
{
username: '',
friends:[], <--- Pulled from the server with async middleware
connections:[], <--- Connections data here ???
}
But I would go on and say, that such a device subscription or media stream is not serializable and therefore it would be not proper, to hold them in the Redux Appstate.
And i'm aware, that for example for server request, one is encouraged to use middleware. So for friends of the user, one would write asynchronous actions to pull the friends user names from the server at the login of a user. But a device id in the state wont do, since one has to actually interact with the device connection stream in the app.
So would writing a seperate middleware be an acceptable way to hold on to such data? What is the common practice herefore?

Where to place domain services in AxonIQ

I have a user aggregate which is created using CreateUser command which consists of aggregate identifier and username.
Along with that i have domain service that communicates with mongo db and checks if username exists, if not it puts it there.
eg registerUsername(username) -> true / false whether it registered it or not
My question is, would it be good idea to create command handler on top of the user aggregate that would handle the CreateUser command and whether it has username or not will dispatch proper commands/events? like so:
#Component
class UserCommandHandler(
#Autowired
private val repository: Repository<User>,
#Autowired
private val eventBus: EventBus,
#Autowired
private val service: UniqueUserService
) {
#CommandHandler
fun createUser(cmd: CreateUser) {
if (this.service.registerUsername(cmd.username)) {
this.repository.newInstance { User(cmd.id) }
.handle(GenericCommandMessage(cmd))
} else {
this.eventBus.publishEvent(UserCreateFailed(cmd.id, cmd.username))
}
}
}
This question is not necessarily related to the set uniqueness in ddd but more of a question where should i put dependency of domain services? I could probably create user registration saga and inject that service inside saga but i think saga should only rely on command dispatching and not have any if/else logic.
I think the place to put your domain service depends on the use case at hand.
I typically try to have domain service do virtual no outbound calls to other services or databases, at all.
The domain service you're now conceiving however does exactly that to, like you're point out, solve the uniqueness issue.
In this situation, you could likely come by with the suggested approach.
You could also think of introducing a MessageHandlerInterceptor (or even fancier, a HandlerEnhancerDefinition as described here), specifically triggering on the create command and performing the desired check.
If it would be domain service like I depicted mine just now (e.g. zero outbound calls from domain service), then you can safely wire it in your command handling functions to perform some action.
If you're in a Spring environment, simply having your domain service as a bean and providing it as a parameter to your message handling function is sufficient for Axon to resolve it for you (through the means of ParameterResolvers, as described here).
Hope this helps you out #PolishCivil!

REQUEST_DENIED when using Google Maps AutoComplete

I am unable to use Google Maps AutoComplete. I have read all the articles about this problem, and I still get REQUEST_DENIED:
The following services are turned ON:
Google Maps API v3
Places API
Prediction API
Simple API Access:
API key: **
Referers: Any referer allowed
Activated on: (A few days ago)
Activated by: ** – you
I have even activated my credit card (don't know if that makes a difference for traffic under the quota):
The following happens (tested both from a browser and command line cURL):
https://maps.googleapis.com/maps/api/place/autocomplete/json?input=New&types=(cities)&key=$apikey
{
"predictions" : [],
"status" : "REQUEST_DENIED"
}
How do I make this work?
From the documentation
Required parameters
input — The text string on which to search. The Place service will return candidate matches based on this string and order results based on their perceived relevance.
sensor — Indicates whether or not the Place request came from a device using a location sensor (e.g. a GPS) to determine the location sent in this request. This value must be either true or false.
key — Your application's API key. This key identifies your application for purposes of quota management. Visit the APIs Console to select an API Project and obtain your key. Maps API for Business customers must use the API project created for them as part of their Places for Business purchase.
I don't see "sensor" in your example request.

Resources