I have an address in my database that I've put into a location hash. The hash contains separate keys for streetAddress, city, state, and zipCode. I've nested the data like so in my graphql schema file:
location: {
streetAddress: {
type: String,
required: true,
unqiue: true
},
city: {
type: String,
required: true
},
state: {
type: String,
required: true
},
zipCode: {
type: Number,
required: true
}
}
And I've implemented the schema type like this:
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
id: {type: GraphQLID},
phoneNum: { type: GraphQLString },
location: {
streetAddress: { type: GraphQLString },
city: { type: GraphQLString },
state: { type: GraphQLString },
zipCode: { type: GraphQLInt }
}
...
However, I get an error message saying that the output type is undefined when I try to do a query in graphql:
"message": "The type of RestaurantType.location must be Output Type but got: undefined."
I believe I understand where the error is coming from; I'm assuming that it expects location to have a type as well. What would be the correct syntax for doing this/fixing this error message?
As you guessed, you cannot have nested fields like that. You need to create a separate type for every object in your schema. First create the type:
const Location = new GraphQLObjectType({
name: 'Location',
fields: () => ({
streetAddress: { type: GraphQLString },
city: { type: GraphQLString },
state: { type: GraphQLString },
zipCode: { type: GraphQLInt }
}),
})
Then use it:
const Restaurant = new GraphQLObjectType({
name: 'Restaurant',
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
location: { type: Location },
}),
})
or if you don't need to reuse the type, you can define it inline like this:
const Restaurant = new GraphQLObjectType({
name: 'Restaurant',
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
location: {
type: new GraphQLObjectType({
name: 'Location',
fields: () => ({
streetAddress: { type: GraphQLString },
city: { type: GraphQLString },
state: { type: GraphQLString },
zipCode: { type: GraphQLInt }
}),
})
},
}),
})
I create DateTime picker in Strapi with the required field validation but can't save. occurring following error.
apI Parametr
components: []
contentType: {name: "Events", description: "", connection: "default", collectionName: "events",…}
name: "Events"
description: ""
connection: "default"
collectionName: "events"
attributes: {title: {type: "string", required: true},…}
title: {type: "string", required: true}
created_by: {nature: "oneWay", target: "plugins::users-permissions.user", dominant: false, unique: false}
image: {type: "media", multiple: false, required: true}
seo_description: {type: "text"}
seo_title: {type: "string"}
description: {type: "richtext", required: true}
calendly_url: {type: "string"}
start_date: {type: "datetime", required: true}
type: "datetime"
required: true
end_date: {type: "datetime"}
PUT http://localhost:1337/content-type-builder/content-types/application::events.events 400 (Bad Request)```
Below is my api.yml:
openapi: 3.0.0
info:
title: 'AutoDelievery API'
description: 'AutoDelievery API Documentation'
termsOfService: 'https://www.yopmail.com'
contact:
name: yopmail
url: 'http://www.yopmail.com'
email: contactus#yopmail.com
license:
name: yopmail
url: 'http://www.yopmail.com/licenses/yopmail-AutoDelievery-Licence.html'
version: 1.0.0-oas3
servers:
-
url: 'http://localhost:5055/'
tags:
-
name: AutoDelievery
description: 'AutoDelievery product related APIs'
externalDocs:
description: 'Documentation:'
url: 'http://localhost:5055/external/doc'
paths:
/autoDelievery:
post:
tags: [autoDelievery]
summary: 'Creates a new autoDelievery record'
operationId: insertSubscription
requestBody: {description: 'autoDelievery request body', content: {application/json: {schema: {$ref: '#/components/schemas/AutoDelievery'}}}}
responses: {'200': {description: 'successful operation', content: {application/json: {schema: {$ref: '#/components/schemas/AutoDelievery'}}}}, '400': {description: 'Bad Request', content: {application/json: {schema: {$ref: '#/components/schemas/AutoDelieveryError'}}}}, '500': {description: 'Server Error', content: {application/json: {schema: {$ref: '#/components/schemas/AutoDelieveryError'}}}}}
'/autoDelievery/{autoDelieveryID}':
get:
tags: [AutoDelievery]
summary: 'AutoDelievery as per ID'
description: 'Fetches the AutoDelievery for the provided Id'
operationId: getAutoDelieveryById
parameters: [{in: path, name: autoDelieveryID, required: true, schema: {type: string}}]
responses: {'200': {description: 'successful operation', content: {application/json: {schema: {$ref: '#/components/schemas/AutoDelievery'}}}}, '400': {description: 'Server Error', content: {application/json: {schema: {$ref: '#/components/schemas/AutoDelieveryError'}}}}}
delete:
tags: [autoDelievery]
summary: 'Delete AutoDelievery as per ID'
description: 'Finds the autoDelievery for the provided Id and deletes the same'
operationId: deleteAutoDelieveryById
parameters: [{in: path, name: autoDelieveryID, required: true, schema: {type: string}}]
responses: {'200': {description: 'successful operation', content: {application/json: {schema: {$ref: '#/components/schemas/AutoDelievery'}}}}, '400': {description: 'Server Error', content: {application/json: {schema: {$ref: '#/components/schemas/AutoDelieveryError'}}}}}
'/autoDelievery/{autoDelieveryID}/payment':
put:
tags: [AutoDelievery]
summary: 'Updates autoDelievery payment details'
parameters: [{in: path, name: autoDelieveryID, description: 'AutoDelievery Id of which payment details are to be updated', required: true, schema: {type: string}}]
operationId: updatePayment
requestBody: {content: {application/json: {schema: {$ref: '#/components/schemas/PaymentMethod'}}}}
responses: {'200': {description: 'successful operation', content: {application/json: {schema: {$ref: '#/components/schemas/AutoDelievery'}}}}, '400': {description: 'Bad Request', content: {application/json: {schema: {$ref: '#/components/schemas/AutoDelieveryError'}}}}, '500': {description: 'Server Error', content: {application/json: {schema: {$ref: '#/components/schemas/AutoDelieveryError'}}}}}
'/autoDelievery/{autoDelieveryId}/frequency':
put:
tags: [AutoDelievery]
summary: 'Updates AutoDelievery frequency, quantity and end data.'
parameters: [{in: path, name: autoDelieveryId, description: 'AutoDelievery Id of which frequency is to be updated', required: true, schema: {type: string}}]
operationId: updateFrequency
requestBody: {content: {application/json: {schema: {$ref: '#/components/schemas/Frequency'}}}}
responses: {'200': {description: 'successful operation', content: {application/json: {schema: {$ref: '#/components/schemas/AutoDelievery'}}}}, '400': {description: 'Bad Request', content: {application/json: {schema: {$ref: '#/components/schemas/AutoDelieveryError'}}}}, '500': {description: 'Server Error', content: {application/json: {schema: {$ref: '#/components/schemas/AutoDelieveryError'}}}}}
components:
schemas:
SubscriptionList:
type: object
properties: {count: {type: integer}, result: {type: array, items: {$ref: '#/components/schemas/AutoDelievery'}}, page: {type: integer}}
DataEntity:
type: object
properties: {id: {type: string}, lastModifiedDate: {type: string}, createdDate: {type: string}}
AutoDelievery:
allOf: [{$ref: '#/components/schemas/DataEntity'}, {type: object, required: [userId, clientId, quantity, frequency, payment, product, shippingAddress], properties: {userId: {type: string}, clientId: {type: string}, parentSubscriptionId: {type: string}, product: {$ref: '#/components/schemas/Product'}, quantity: {type: integer, minimum: 1}, frequency: {type: number, minimum: 1}, payment: {$ref: '#/components/schemas/PaymentMethod'}, paymentMethodId: {type: string}, shippingMethodId: {type: string}, nextOrderDate: {type: string}, subscriptionStartDate: {type: string}, subscriptionEndDate: {type: string}, shippingMethod: {type: string}, shippingAddress: {$ref: '#/components/schemas/Address'}}}]
Product:
type: object
required: [productId]
properties: {productId: {type: string}, productDescription: {type: string}}
PaymentMethod:
type: object
required: [billingAddress]
properties: {createdDate: {type: string}, modifiedDate: {type: string}, paymentType: {type: string}, billingAddress: {$ref: '#/components/schemas/Address'}}
discriminator: {propertyName: paymentType}
Frequency:
type: object
required: [frequency, quantity]
properties: {frequency: {type: number, minimum: 1}, subscriptionEndDate: {type: string}, quantity: {type: integer, minimum: 1}}
Card:
allOf: [{$ref: '#/components/schemas/PaymentMethod'}, {type: object, required: [nameOnCard, lastFourDigits, expiryMonth, expiryYear], properties: {nameOnCard: {type: string}, lastFourDigits: {type: string}, token: {type: string}, expiryMonth: {type: string, minLength: 2, maxLength: 2}, expiryYear: {type: string, format: year}}, discriminator: {propertyName: paymentType}}]
PayPal:
allOf: [{$ref: '#/components/schemas/PaymentMethod'}, {type: object, required: [accountId], properties: {accountId: {type: string}}}]
Payment:
type: object
properties: {payment: {allOf: [{$ref: '#/components/schemas/PaymentMethod'}], discriminator: {propertyName: paymentType}}}
Address:
type: object
required: [firstName, lastName, addressLine1, city, state, postalCode, country]
properties: {prefix: {type: string}, firstName: {type: string}, middleName: {type: string}, lastName: {type: string}, suffix: {type: string}, title: {type: string}, companyName: {type: string}, addressLine1: {type: string}, addressLine2: {type: string}, city: {type: string}, state: {type: string}, postalCode: {type: string}, country: {type: string}, phoneNumber: {type: string}, mobilePhoneNumber: {type: string}}
Status:
type: object
required: [status]
properties: {status: {type: string}, details: {type: string}}
Shipping:
type: object
properties: {shippingMethodId: {type: string}, shippingMethod: {type: string}}
PaymentAuthorization:
type: object
properties: {authId: {type: string}}
CommerceItem:
type: object
required: [subscriptionId, quantity, product]
properties: {subscriptionId: {type: string}, product: {$ref: '#/components/schemas/Product'}, quantity: {type: number, minimum: 1}, itemUnitPrice: {type: number}, itemTotalPrice: {type: number}, itemDiscount: {type: number}}
ErrorResponse:
type: object
required: [errorMessage]
properties: {field: {type: string}, errorMessage: {type: string}}
ErrorResponseList:
type: object
required: [errors]
properties: {errors: {type: array, items: {$ref: '#/components/schemas/ErrorResponse'}}}
NoSubscriptionResponse:
allOf: [{$ref: '#/components/schemas/ErrorResponseList'}]
AutoDelieveryError:
allOf: [{$ref: '#/components/schemas/ErrorResponseList'}]
NoOrderResponse:
allOf: [{$ref: '#/components/schemas/ErrorResponseList'}]
my sample api is:
"id": "string",
"lastModifiedDate": "string",
"createdDate": "string",
"userId": null,
"clientId": "string",
"parentSubscriptionId": "string",
"product": {
"productId": "string",
"productDescription": "string"
},
"quantity": 0,
"frequency": 0,
"payment": {
"createdDate": "string",
"modifiedDate": "string",
"paymentType": "string",
"billingAddress": {
"prefix": "string",
"firstName": "string",
"middleName": "string",
"lastName": "string",
"suffix": "string",
"title": "string",
"companyName": "string",
"addressLine1": "string",
"addressLine2": "string",
"city": "string",
"state": "string",
"postalCode": "string",
"country": "string",
"phoneNumber": "string",
"mobilePhoneNumber": "string"
}
},
"paymentMethodId": "string",
"shippingMethodId": "string",
"nextOrderDate": "string",
"subscriptionStartDate": "string",
"subscriptionEndDate": "string",
`enter code here`"shippingMethod": "string",
"shippingAddress": {
"prefix": "string",
"firstName": "string",
"middleName": "string",
"lastName": "string",
"suffix": "string",
"title": "string",
"companyName": "string",
"addressLine1": "string",
"addressLine2": "string",
"city": "string",
"state": "string",
"postalCode": "string",
"country": "string",
"phoneNumber": "string",
"mobilePhoneNumber": "string"
}
}
I get an error response in the following format:
{
"errors": [
{
"field": "userId",
"errorMessage": "must not be null"
}
]
}
What should I do to have a customized error message?
This can be easily solved by adding a ControllerAdvice class. Figure out the exception being thrown from the stacktrace and write a handler for the same. In the handler you will be able to throw custom error messages, when ever this kind of exception occurs.
Here is some reference for ExceptionHandler
Swagger puts #NotNull annotation on required fields while creating POJO.
Message interpolation can be done by creating ValidationMessages.properties file in the classpath as follows:
javax.validation.constraints.NotNull.message=CUSTOMIZED ERROR MESSAGE
It will override the default error message which comes from
/org/hibernate/validator/ValidationMessages.properties
You can implement spring's abstract class OncePerRequestFilter and override
doFilterInternal method .
Inside this method add validation using httpservletRerquest and return the custom message using ResponseStatusException .
ref- https://www.baeldung.com/spring-onceperrequestfilter