I need to consume a graphQL API in Mule 4.
i draft below json code in dataweave, then use HTTP requestor to post the payload.
but still return Invalid Syntax, may i know is it possible to post data to graphQL API
in Mule 4? what's syntax error in below code?
%dw 2.0
output application/json
---
{
query: "query{
test (first: 10, status: \"ACTIVE\" ) {
edges {
node {
id
ref
type
status
attributes {
name
value
type
}
}
}
}"
}
Yes it is possible to post data to GraphQL API in Mule 4. The Error that you are getting is probably because you are missing a closing parenthesis in your query. Try this
%dw 2.0
output application/json
---
{
query: "query{
test (first: 10, status: \"ACTIVE\" ) {
edges {
node {
id
ref
type
status
attributes {
name
value
type
}
}
}
}
}"
}
Related
I'm trying to create a simple Spring GraphQL subscription handler. Here's my controller:
#Controller
public class GreetingController {
#QueryMapping
String sayHello() {
return "Hello!";
}
#SubscriptionMapping
Flux<String> greeting(#Argument int count) {
return Flux.fromStream(Stream.generate(() -> "Hello # " + Instant.now()))
.delayElements(Duration.ofSeconds(1))
.take(count);
}
}
Here's the GraphQL schema:
type Query {
sayHello: String
}
type Subscription {
greeting(count: Int): String
}
Spring configuration:
spring:
graphql:
graphiql:
enabled: true
path: /graphiql
When I try to run above subscription using graphiql hosted by the spring I receive following error:
{
"errors": [
{
"isTrusted": true
}
]
}
When I run the same graphql request using Postman I receive following response:
{
"data": {
"upstreamPublisher": {
"scanAvailable": true,
"prefetch": -1
}
}
}
What is causing the subscription not to return data from my controller?
As explained in the linked GitHub issue, a subscription requires the ability to stream data within a persistent transport connection - this is not available other plain HTTP.
You'll need to enable WebSocket support in your application first. The GraphiQL UI should use the WebSocket transport transparently for this.
I have an application that uses a GraphQL API, provided by the AWS AppSync service. It uses GraphQL subscriptions to send messages between different clients in near real time. There is a mutation pushItems that's configured with a resolver, which has a 'none' data source and forwards the request data unmodified to the subscription onItemChange.
The app hasn't been used for a couple of years, and now when I attempt to trigger a subscription event, I get an error on the subscribed client. Previously this worked without issues.
{
"data": {
"onItemChange": null
},
"errors": [
{
"message": "Cannot return null for non-nullable type: 'ID' within parent 'Item' (/onItemChange/id)",
"path": [
"onItemChange",
"id"
]
}
]
}
The error message suggests that the property id within the Item object is null, however when I send a mutation from the AWS AppSync web console with a hard-coded string for the item ID, I still get the same issue, even though the mutation response contains the correct data that should be forwarded to the subscribed client.
I've created a minimal configuration in AWS AppSync to reproduce the issue, which is detailed below. Is it possible that the AppSync service has changed the way it handles subscription data in the last few years?
GraphQL schema
schema {
query: Query
mutation: Mutation
subscription: Subscription
}
type Query {
getItem(id: ID!): Item
}
type Mutation {
pushItems(
items: [ItemInput]
): [Item]}
type Subscription {
onItemChange: Item
#aws_subscribe(
mutations: [
"pushItems"
]
)
}
type Item {
id: ID!
}
input ItemInput {
id: ID!
}
Resolver mappings for mutation pushItems
Request:
{
"version" : "2017-02-28",
"payload": $util.toJson($context.arguments.items)
}
Response:
$util.toJson($context.result)
Example queries
The following queries can be used to reproduce the issue in the AWS AppSync web console. First, subscribe to onItemChange:
subscription MySubscription {
onItemChange {
id
}
}
Then (in a different browser tab) send some data to pushItems:
mutation MyMutation {
pushItems(items: [{id: "foo"}]) {
id
}
}
You are returning Set of items in the mutation so you should update subscription return type to [Item]
type Subscription {
onItemChange: [Item] <--- HERE
#aws_subscribe(mutations: ["pushItems"])
}
I've never used GraphQL before so I am really lacking knowledge on how to go about this. I'm wanting to update product meta fields on Shopify and it appears this is the only way. What I've done so far is really fumbling...
My JSON is:
{
"input": {
"id": "gid://shopify/Product/749521178847",
"metafields": [
{
"id": "gid://shopify/Metafield/2223333",
"value": "Training Grounds"
}
]
}
}
I've minified this to:
{"input":{"id":"gid://shopify/Product/749521178847","metafields":[{"id":"gid://shopify/Metafield/2223333","value":"The Training Grounds"}]}}
And am then using an HTTP request to:
https://MYSTORE.myshopify.com/api/2021-10/graphql.json?query={"input":{"id":"gid://shopify/Product/749521178847","metafields":[{"id":"gid://shopify/Metafield/2223333","value":"The Training Grounds"}]}}
I get the error:
SyntaxError: JSON.parse: unexpected end of data at line 1 column 1 of the JSON data
I don't know if any of this is correct. If it is, I don't know if ?query= is the right variable to pass it through on.
I recommend you start using Postman, thunder client, or similar to write your graphql queries first, you will learn a lot about how graphql works and the error msgs will be a lot more useful.
To easily connect with Shopify on this stage, go to a store and create a private app, now you can use this for authenticating your API calls.
After that the Shopify graphql works on POST, you can't write your request on GET mode.
It needs to be a POST and you are missing type of operation mutation in this case and what it is.
Postman has https://www.postman.com/lively-moon-541169/workspace/purego-apis/example/16545848-bf0d1589-09b1-4ec6-ba63-a65a56b500eb examples of how to do the calls which can help you.
Also you can check GraphiQL app on shopify to test all the queries before making the programmatic queries
Updating an existing metafield:
mutation {
metafieldsSet(metafields: [
{namespace: "YOURNAMESPACE", ownerId: "gid://shopify/Customer/CUSTOMER_ID", type: "single_line_text_field", key: "YOURKEY", value: "THIS IS NEW VALUE"}
]) {
metafields {
key
value
}
userErrors {
field
message
}
}
}
Creating new metafield:
mutation {
customerUpdate(input: {
id: "gid://shopify/Customer/CUSTOMER_ID",
metafields: [
{key: "newkey", value: "some value", type: "single_line_text_field", namespace: "some namespace"},
]
}) {
userErrors {
field
message
}
}
}
I have this query:
query SessionQuery {
cliente {
id
clienteId
rut
porcentajeDeCompletitudDeInformacion
fichaCliente {
tipoPersona
razonSocial
}
representantesLegales {
edges {
node {
rutRepresentante
}
}
}
documentosRequeridos {
edges {
node {
iDDocumento
cargado
nombreDocumento
tipoDocumentoHQB
}
}
}
}
usuario {
id
usuarioId
email
nombre
rut
}
}
I'm testing for the first time GraphQL through Postman, like this way:
I'm having this response, I don't understand the error message:
{"data":{"cliente":{"id":"Q2xpZW50ZTow","clienteId":0,"rut":"XXX","porcentajeDeCompletitudDeInformacion":20,"fichaCliente":{"tipoPersona":2,"razonSocial":"ING. Y SISTEMAS BIZWARE (Empresa Relacionada)"},"representantesLegales":{"edges":[{"node":{"rutRepresentante":null}}]},"documentosRequeridos":{"edges":[]}},"usuario":{"id":"VXN1YXJpbzoyMDI4","usuarioId":2028,"email":"XXXX#gmail.com","nombre":"XXXX","rut":"XXXX"}},"errors":[{"message":"GraphQL.ExecutionError: Cannot return null for non-null type. Field: rutRepresentante, Type: String!.\r\n at GraphQL.Execution.ExecutionStrategy.ValidateNodeResult(ExecutionContext context, ExecutionNode node)\r\n at GraphQL.Execution.ExecutionStrategy.ExecuteNodeAsync(ExecutionContext context, ExecutionNode node)","locations":[{"line":14,"column":11}],"path":["cliente","representantesLegales","edges","0","node","rutRepresentante"]}]}
I not sure what it means the error. My problem is when I call this Graphql endpoint from JavaScript I have a CORS problem in my app, but I detected with Postman that maybe the problem is this one, and the query or something is broken. Any idea please, thanks.
xadm's comment is correct - in a standard GraphQL schema, the exclamation point means that the field is required. It's likely that the rutRepresentante field is NULL for the database record that your query retrieves.
Either remove the exclamation mark from String! in order to make the field nullable, or populate the row in the database for the rutRepresentante column (or key, if you're not using SQL...)
For a mutation addVoucher there are a limited list of potential errors that can occur.
Voucher code invalid
Voucher has expired
Voucher has already been redeemed
At the moment I'm throwing a custom error when one of these occurs.
// On the server:
const addVoucherResolver = () => {
if(checkIfInvalid) {
throw new Error('Voucher code invalid')
}
return {
// data
}
}
Then on the client I search the message description so I can alert the user. However this feels brittle and also the GraphQL API doesn't automatically document the potential errors. Is there a way to define the potential errors in the GraphQL schema?
Currently my schema looks like this:
type Mutation {
addVoucherResolver(id: ID!): Order
}
type Order {
cost: Int!
}
It would be nice to be able to do something like this:
type Mutation {
addVoucherResolver(id: ID!): Order || VoucherError
}
type Order {
cost: Int!
}
enum ErrorType {
INVALID
EXPIRED
REDEEMED
}
type VoucherError {
status: ErrorType!
}
Then anyone consuming the API would know all the potential errors. This feels like a standard requirement to me but from reading up there doesn't seem to be a standardises GraphQL approach.
It's possible to use a Union or Interface to do what you're trying to accomplish:
type Mutation {
addVoucher(id: ID!): AddVoucherPayload
}
union AddVoucherPayload = Order | VoucherError
You're right that there isn't a standardized way to handle user-visible errors. With certain implementations, like apollo-server, it is possible to expose additional properties on the errors returned in the response, as described here. This does make parsing the errors easier, but is still not ideal.
A "Payload" pattern has emerged fairly recently for handling these errors as part of the schema. You see can see it in public API's like Shopify's. Instead of a Union like in the example above, we just utilize an Object Type:
type Mutation {
addVoucher(id: ID!): AddVoucherPayload
otherMutation: OtherMutationPayload
}
type AddVoucherPayload {
order: Order
errors: [Error!]!
}
type OtherMutationPayload {
something: Something
errors: [Error!]!
}
type Error {
message: String!
code: ErrorCode! # or a String if you like
}
enum ErrorCode {
INVALID_VOUCHER
EXPIRED_VOUCHER
REDEEMED_VOUCHER
# etc
}
Some implementations add a status or success field as well, although I find that making the actual data field (order is our example) nullable and then returning null when the mutation fails is also sufficient. We can even take this one step further and add an interface to help ensure consistency across our payload types:
interface Payload {
errors: [Error!]!
}
Of course, if you want to be more granular and distinguish between different types of errors to better document which mutation can return what set of errors, you won't be able to use an interface.
I've had success with this sort of approach, as it not only documents possible errors, but also makes it easier for clients to deal with them. It also means that any other errors that are returned with a response should serve as an immediately red flag that something has gone wrong with either the client or the server. YMMV.
You can use scalar type present in graphql
just write scalar JSON and return any JSON type where you want to return it.
`
scalar JSON
type Response {
status: Boolean
message: String
data: [JSON]
}
`
Here is Mutation which return Response
`
type Mutation {
addVoucherResolver(id: ID!): Response
}
`
You can return from resolver
return {
status: false,
message: 'Voucher code invalid(or any error based on condition)',
data: null
}
or
return {
status: true,
message: 'Order fetch successfully.',
data: [{
object of order
}]
}
on Front end you can use status key to identify response is fetch or error occurs.