Filter: [?] can not be applied to primitives processing Spring Cloud Contract DSL - jsonpath

I have a Spring Cloud Contract DSL that looks like this:
package contracts.someconsumer.messaging
import org.springframework.cloud.contract.spec.Contract
Contract.make {
label 'my_label'
// input to the contract
input {
// the contract will be triggered by a method
triggeredBy('someMethodThatSendsMessage()')
}
// output message of the contract
outputMessage {
// destination to which the output message will be sent
sentTo 'Consumer.contractTest.VirtualTopic.some_destination'
// the body of the output message
body([
id: value(consumer('11111111-2222-3333-4444-555555555555'),producer(regex(uuid()))),
correlationId: value(producer(regex(uuid()))),
service: 'MY_SERVICE',
payload:
[
email: 'test#example.com'
]
])
}
}
Without the "payload" part everything works great. With the payload, I encounter this exception:
com.jayway.jsonpath.InvalidPathException: Filter: [?] can not be applied to primitives. Current context is: {"email":"test#example.com","legalName":"ACME Inc"}
at com.jayway.jsonpath.internal.path.PredicatePathToken.evaluate(PredicatePathToken.java:66) ~[json-path-2.2.0.jar:2.2.0]
at com.jayway.jsonpath.internal.path.PathToken.handleObjectProperty(PathToken.java:81) ~[json-path-2.2.0.jar:2.2.0]
at com.jayway.jsonpath.internal.path.PropertyPathToken.evaluate(PropertyPathToken.java:79) ~[json-path-2.2.0.jar:2.2.0]
at com.jayway.jsonpath.internal.path.RootPathToken.evaluate(RootPathToken.java:62) ~[json-path-2.2.0.jar:2.2.0]
The relevant line from the generated test:
assertThatJson(parsedJson).field("['payload']").field("['email']").isEqualTo("test#example.com");
Just a little more info, this is what the serialized message looks like:
2017-09-21 08:32:03.721 INFO 10716 --- [ main] c.v.sccdemo.producer.InviteServiceImpl : Event: {"id":"e63de44e-6e1a-4c4e-b98b-3c49a49efc9c","destination":"VirtualTopic.some_destination","correlationId":"8efb9740-5651-4068-8a6e-574ae7759552","service":"MY_SERVICE","payload":"{\"email\":\"test#example.com\",\"legalName\":\"ACME Inc\"}","timestamp":1505997123576,"version":"v1"}
Am I doing something wrong in the DSL? Is the 'payload' part of the body expressed correctly?

The payload looks wrong... Notice that it's considering payload as a String value instead of a Map. I guess it's enough to change the payload to the proper one and things should work again!

Related

FastAPI pydantic response_model

FastAPI with uvicorn. So far i have everything working fine, now wanted to add extra validation with pydantic and response_model validation. My challange is, the response is a nested object, example:
{
"name": "always the same",
"value": ["ACL1", "ACL2", "ACL3"]
}
I have tried to:
class ACL(BaseModel):
name: str
#app.post(
"get/acls",
response_model=List[ACL]
)
def get_acls(credentials: HTTPBasicCredentials = Depends(security)):
But obviously it will fail. How to define correctly the response model so that it's correctly validated ? (and also visible in openapi documentation page ?)
Thanks,
You can use nested models in Pydantic and by by extension also in FastAPI. Like so:
class ACL(BaseModel):
name: str
class YourResponseModel(BaseModel):
name: str
value: list[ACL]
#app.post("/get/acls", response_model=YourResponseModel)
def get_acl():
return {"name": "always the same", "value": [{"name":"ACL1"}, {"name":"ACL2"}, {"name":"ACL3"}]}
If you don't want nested objects in your value list, then you have to build some logic to parse it. Below is an example of this:
class ACL(BaseModel):
name: str
class AnotherResponseModel(BaseModel):
name: str
value: list[str]
#app.post("/get/acls2", response_model=AnotherResponseModel)
def get_acl():
acls = [ACL(name="ACL1"), ACL(name="ACL2"), ACL(name="ACL3")]
return {"name": "always the same", "value": [acl.name for acl in acls] }
Please note, it is bad practice to mix up POST and GET requests (you are defining a POST endpoint, that will 'get' some ACLs for the end user). That is however unrelated to this question.

Using Request Headers in Query/Mutation

I am following Hasura basic tutorial on creating a todo app https://hasura.io/learn/graphql/hasura-advanced/introduction/ and want to extend it and have few additional operations, but don't seem to be able. Setup is as in the tutorial - you have Tasks table with title, description, authorId, isComplete, isPublic column. Table permissions are setup as in the tutorial, so a user can only select their own or public tasks. They can also update only their own tasks. Operations I want to add:
Query only public tasks that are NOT theirs (additionally, inverse also - only theirs without public ones).
Mutate public tasks to complete that are not theirs (update isComplete without having permissions to other columns).
I could create views for the first case, but it seems too much of an effort for such a simple logic. I think both cases could simply be done with access to Request Header (x-hasura-user-id) like so:
query PublicTasksOnly {
tasks(where: {isPublic: {_eq: true}, authorId: {_neq: x-hasura-user-id}}) {
description
isComplete
title
}
}
But it seems that this is not possible. Any ideas/suggestions how to achieve this?
To my knowledge I do not think it is possible to reference http headers in your graphql queries. Have you tried passing the userId as a variable to the query? Something like the following:
query PublicTasksOnly($userId: String!) {
tasks(where: {isPublic: {_eq: true}, authorId: {_neq: $userId}}) {
description
isComplete
title
}
}
I am not quite sure what you want to achieve but if your problem gets solved by adding this header x-hasura-user-id then I can help you out.
You can copy the graphql endpoint from hasura console and hit simple http request to that endpoint with query and it's variables in request body. Sharing sample code here using http library axios:
import axios from 'axios';
axios({
method: 'post',
url: 'https://your-hasura-project-url.hasura.app/v1/graphql',
headers: { 'x-hasura-user-id': '< Your user id >' },
data: {
query: `query PublicTasksOnly {
tasks(where: {isPublic: {_eq: true}}) {
description
isComplete
title
}
}`,
variables: { userId: 'abc-xyz' }
}
})
This should solve your issue.

How to decode extrinsic at json-RPC call's data(byte code)

I call json-RPC through the terminal and get the data as below.
extrinsics is raw byte, but I'm using polkadot-js(SCALE codec?) to decode it.
But I don't know which method to call.
"block": {
"extrinsics": [
"0x280402000be1da78d37e01","0xd91f..(too long haha)..580"
],
"header": { "digest": { ... }
#polkadot/crypto-util? #polkadot/util? Which module and which method should I use? I want input string(raw data) and get string(json or human data)
please help..

Managing API calls with default error handling in react-redux application

I've completed my application and I'm now integrating the real api calls for each async action. I use redux-thunk which returns a promise from an axios instance.
Currently I'm repeating so much of the same logic in my actions that I'm sure I'm missing something.
API response example
{
"ok": true,
"warnings": [],
"errors": [],
"response": {/* stuff */}
}
The Idea is that I need the same error handling if either the axios call fails (so another response status then 2xx). Additionally I need to also do the same thing when the api response returns "ok": false.
Preferably I would like to dispatch an action which shows a notification to users so they also know when something goes wrong. Aside from that I want to log the api response's warnings and error entities. This is mainly because I'll use sentry for monitoring.
Any Ideas on how to do this without doing a .catch() with the same logic on each api call in any of my action creators?
I've thought about using the onError of axios but that can't dispatch an action as far as I know.
You could use a response interceptor to dispatch appropriate actions. Just wire them up after you create the store
const store = createStore(...)
axios.interceptors.response.use((response) => {
if (!response.data.ok) {
store.dispatch({ type: "RESPONSE_NOT_OK", response }
}
return response
}, (error) => {
store.dispatch({ type: "RESPONSE_HAD_ERROR", error }
return Promise.reject(error)
})
Obviously, you can handle the response how ever you want, this was just for demonstration purposes.

Using Flow union types for Redux actions

Following the style of this Facebook app sample using Redux and Flow together, I made an action type in this manner:
type Action =
| { type: 'ADD_FILES', files: Array<{ id: number, file: File }> }
| { type: 'HANDLE_IMAGE_PUBLISHED', id: number, name: string }
| { type: 'SET_IMAGE_UPLOAD_PROGRESS', id: number, progress: number }
;
But I've found that when I try to process my actions with a reducer, Flow complains if I try to access the name or progress properties, saying "Property not found in object type".
That is, in my reducer, if I check that action.type === 'HANDLE_IMAGE_PUBLISHED' and then access action.name, Flow complains. And the same thing goes for for accessing action.progress property when action.type === 'SET_IMAGE_UPLOAD_PROGRESS'. Both these property accesses should be legit under their respective circumstances, as far as I can tell, but Flow complains.
Yet for some reason it's OK for me to access action.id anywhere, even though one of the types in my union doesn't specify an id property. I'm very confused.
Here is a live demo in the Flow REPL. What am I doing wrong?
This is simply a case of a type refinement invalidation:
https://flow.org/en/docs/lang/refinements/#toc-refinement-invalidations
Because you are using the value in a callback, Flow pessimistically assumes that you could have re-assigned action before the callback runs (it does not know that the map callback is called immediately). It also does not do the analysis to see that there is no place, in fact, that you re-assign it.
All that's needed is to pull the action out as a const:
export default (state: Array<ImageRecordModel> = [], action_: Action): Array<ImageRecordModel> => {
const action = action_;
(tryflow link)
You may also want to consider enabling const params in your .flowconfig. This does basically what you expect: treats all params as const:
[options]
experimental.const_params=true

Resources