简体   繁体   中英

Graphql_flutter mutation running on playground doesn't work on running device/emulator

During my project development, I'm using flutter with graphql, for testing purpose tried mutation on playground and passed the test, but on device and emulator getting error response with 5xx, I know this is "server side" error but tested same mutation from our webpage and it is working too. Beside with flutter, I am using following packages:

  • equatable: ^1.2.5
  • gql: ^0.12.4
  • graphql: ^4.0.0
  • graphql_flutter: ^4.0.1
  • json_annotation: ^3.1.1
  • meta: ^1.3.0
  • artemis: ^6.18.4
  • build_runner: ^1.11.1
  • json_serializable: ^3.5.1

Till now on this project, I run almost 10 mutations successfully with this file syntax:

  • myproject/
    • graphql/
      • queries/
        • register.graphql -> running well
        • createOffer.graphql -> getting 500 error
      • schema.graphql
    • lib/
      • models/
        • ...generatedModels here..
      • views/
        • register.dart
        • createOffer.dart

register.graphql

mutation signUp(
    $company_name:String!,
    $email: String!,
    $firstname: String!,
    $lastname: String!,
    $phone: String!,
    $tin_ein_number: String!,
) {
    createShipperUser(
        company_name: $company_name,
        email: $email,
        firstname: $firstname,
        lastname: $lastname,
        phone: $phone,
        tin_ein_number: $tin_ein_number,
    ) {
        id
    }
}

register.dart

Widget buildFormBody(BuildContext context) {
    return Mutation(
      options: MutationOptions(
        document: SignUpMutation().document,
        onCompleted: (dynamic resultData) {
          if (resultData != null) {
            onRegistered();
          }
        },
        if (e.linkException != null) {
            showSnackbar(context,
                'Something went wrong, please check your network connection and try again.');
            return;
        }
        final validationErrors = findValidationErrors(
            e.graphqlErrors,
            [
              'firstname',
              'lastname',
              'email',
              'phone',
              'tin_ein_number',
              'company_name',
            ],
          );
          if (validationErrors.isNotEmpty) {
            setState(() {
              firstnameError = validationErrors['firstname'];
              surnameError = validationErrors['lastname'];
              emailError = validationErrors['email'];
              phoneError = validationErrors['phone'];
              if (isTin) {
                einError = null;
                tinError = validationErrors['tin_ein_number'];
              } else {
                einError = validationErrors['tin_ein_number'];
                tinError = null;
              }
              companyError = validationErrors['company_name'];
            });
            //TODO text
            showSnackbar(context, 'Please check entered fields');
          } else if (e.graphqlErrors.isNotEmpty) {
            showSnackbar(
                context, e.graphqlErrors[0].message ?? 'Something went wrong');
          } else {
            showSnackbar(context, 'Something went wrong');
          }
          builder: (runMutation, result) {
           isLoading = result.isLoading;
           return Form( 
             ElevatedButton(
               onPressed: () => onSubmitTap(runMutation),
               child: Text(
                              'Submit',
                              style: TextStyle(
                                  fontSize: 16, fontWeight: FontWeight.w700),
               ),
             )         
           );
        
  void onSubmitTap(RunMutation runMutation) {
    hideKeyboard();
    if (isLoading) {
      return;
    }

    if (formKey.currentState.validate()) {
      formKey.currentState.save();

      setState(() {
        savedPhone = getPhoneMask(savedPhone);
      });

      runMutation(SignUpArguments(
        company_name: savedCompany,
        email: savedEmail,
        phone: savedPhone,
        tin_ein_number: isTin ? 'tin_$savedTin' : 'ein_$savedEin',
        firstname: savedFirstname,
        lastname: savedSurname,
      ).toJson());
    }
  }

And following are mutation getting 500 error.

createOffer.graphql

Mutation(
                      options: MutationOptions(
                        document: CreateShipmentMutation().document,
                        errorPolicy: ErrorPolicy.all,
                        update: (GraphQLDataProxy cache, QueryResult result) {
                          if (result.hasException) {
                            print(result.exception);
                          }
                        },
                        onCompleted: (dynamic resultData) {
                          if (resultData != null) {
                            print('completed');
                            print(resultData);
                            // onCreated();
                          }
                        },
                        onError: (e) {
                          if (e.linkException != null) {
                            showSnackbar(context,
                                'Something went wrong, please check your network connection and try again.');
                            return;
                          }

                          if (e.graphqlErrors.isNotEmpty) {
                            debugPrint(e.graphqlErrors.toString(),
                                wrapWidth: 1024);
                          } else {
                            showSnackbar(context, 'Something went wrong');
                          }
                        },
                      ),
                      builder: (runMutation, result) {
                        isLoading = result.isLoading;
                        return Card(
                          child: ElevatedButton(
                                    onPressed: () => onReviewTap(runMutation),
                                    style: ElevatedButton.styleFrom(
                                        padding:
                                            EdgeInsets.symmetric(vertical: 14)),
                                    child: AnimatedSwitcher(
                                      duration: Duration(milliseconds: 150),
                                      child: result.isLoading
                                          ? Theme(
                                              data: Theme.of(context).copyWith(
                                                  accentColor: Colors.white),
                                              child:
                                                  const ProgressIndicatorSmall(),
                                            )
                                          : Text(
                                              'Review Shipment',
                                              style: TextStyle(
                                                  fontSize: 16,
                                                  fontWeight: FontWeight.w700),
                                            ),
                                    ),
                                  ),
                        );

void onReviewTap(RunMutation runMutation) {
    final acces = accessories
        .map((accessory) {
          if (accessory.isChecked) {
            return accessory.enumType;
          }
        })
        .where((element) => element != null)
        .toList();
    final stops = isMultipleStops ? items : p2pitems;

    hideKeyboard();
    if (isLoading) {
      return;
    }

    runMutation(CreateShipmentArguments(
      input: OfferInput(
        openPrice: 30,
        shipment: CreateShipmentInput(
          requestedTruckTypes: [
            TruckTypesEnum.dryVan,
          ],
          accessorials: [
            AccessorialsEnum.twicRequired,
            AccessorialsEnum.ppe,
          ],
          trailer: TrailerInput(
            temperatureMax: 0,
            temperatureMin: 0,
            temperatureUnit: TemperatureUnitsEnum.f,
          ),
          items: [
            ItemInput(
              description: "Items description",
              weight: WeightInput(
                weight: 100,
                weightUnit: WeightUnitTypesEnum.lb,
              ),
              units: UnitInput(
                unitCount: 0,
                unitType: ItemUnitTypesEnum.units,
              ),
              handlingPiece: HandlingPieceInput(
                pieceCount: 0,
                pieceType: ItemPieceTypesEnum.pallets,
              ),
            ),
          ],
          shortName: "Dem23",
          loadDescription: "adhjahsdhajsdj",
          routeDistanceMiles: 0.0,
          routeDurationMinutes: 0,
          stops: [
            CreateStopInput(
                appointmentType: AppointmentTypesEnum.alreadyMade,
                startTime: "2021-05-03T00:00:00+02:00",
                type: StopTypesEnum.pickup,
                loadingType: LoadingTypesEnum.live,
                locationInput: LocationInput(
                  locationName: "HOUSTON",
                  coordinates:
                      CoordinatesInput(lat: 29.608774, lng: -95.516164),
                  address: AddressInput(
                      full:
                          "14810 Fairway Pines Dr, Missouri City, TX 77489, USA",
                      city: "Missouri City",
                      state: "TX",
                      street: "Fairway Pines Drive",
                      streetNumber: 14810),
                  operationalContact: ContactInput(
                      contactName: "mr contact",
                      email: "hojayevkoch@gmail.com",
                      phoneNumber: "862615986",
                      notes: "notes lorem ipsum"),
                  schedulingContact: ContactInput(
                      contactName: "mr contact",
                      email: "hojayevkoch@gmail.com",
                      phoneNumber: "862615986",
                      notes: "notes lorem ipsum"),
                )),
            CreateStopInput(
              appointmentType: AppointmentTypesEnum.toBeMade,
              startTime: "2021-05-14T05:13:30+00:00",
              endTime: "2021-04-27T17:35:00+00:00",
              type: StopTypesEnum.dropoff,
              loadingType: LoadingTypesEnum.live,
              locationInput: LocationInput(
                locationName: "COSTCO WHO,WEBSTER,TX,USA",
                coordinates: CoordinatesInput(lat: 29.533604, lng: -95.136843),
                address: AddressInput(
                  full: "1310 Jasmine St, Webster, TX 77598, USA",
                  city: "Webster",
                  state: "TX",
                  street: "Jasmine Street",
                  streetNumber: 1310,
                ),
                operationalContact: ContactInput(
                    contactName: "mr contact",
                    email: "mrtest@gmail.com",
                    phoneNumber: "862615986",
                    notes: "notes lorem ipsum"),
                schedulingContact: ContactInput(
                    contactName: "mr contact",
                    email: "mrtest@gmail.com",
                    phoneNumber: "862615986",
                    notes: "notes lorem ipsum"),
              ),
            ),
          ],
        ),
      ),
    ).toJson());

Following are the hardcodes on playground for createOffer:

mutation CreateShipment (
  $input: OfferInput!
) {
  createOffer(input: $input){
    uuid
    shipper_id
  }
}
#variables
{
  "input": {
    "open_price": 30,
    "shipment": {
      "requested_truck_types": [
        "DRY_VAN"   
      ],
      "accessorials": [
        "TWIC_REQUIRED",
        "SHIPPER_REQUIRES_MASK_GLOVES",
        "PPE"
      ],
      "items": [
        {
          "description": "Items description",
          "handling_piece": {
            "piece_type": "PALLETS",
            "piece_count": 0
          },
          "units": {
            "unit_type": "UNITS",
            "unit_count": 0
          },
          "weight": {
            "weight": 100,
            "weight_unit": "LB"
          }
        }
      ],
      "trailer": {
        "temperature_max": 0,
        "temperature_min": 0,
        "temperature_unit": "F"
      },
      "short_name": "Dem",
      "load_description": "load descriotajj adaksdjad",
      "route_distance_miles": 0.0,
      "route_duration_minutes": 0,
      "stops": [
        {
          "appointment_type": "ALREADY_MADE",
          "start_time": "2021-05-03T00:00:00+02:00",
          "type": "PICKUP",
          "loading_type": "LIVE",
          "location_input": {
            "location_name": "HOUSTON",
            "coordinates": {
              "lat": 29.608774,
              "lng": -95.516164
            },
            "address": {
              "full": "14810 Fairway Pines Dr, Missouri City, TX 77489, USA",
              "city": "Missouri City",
              "state": "TX",
              "street": "Fairway Pines Drive",
                    "street_number" :14810
            },
            "operational_contact": {
              "contact_name" : "mr contact",
                    "email" : "mrtest@gmail.com",
                    "phone_number" : "862615986",
                  "notes" : "notes lorem ipsum"
            },
            "scheduling_contact": {
              "contact_name" : "mr contact",
                    "email" : "mrtest@gmail.com",
                    "phone_number" : "862615986",
                  "notes" : "notes lorem ipsum"
            }
          }
        },
        {
          "appointment_type": "TO_BE_MADE",
          "start_time": "2021-05-14T05:13:30+00:00",
          "end_time": "2021-04-27T17:35:00+00:00",
          "type": "DROPOFF",
          "loading_type": "LIVE",
          "location_input": {
            "location_name": "COSTCO WHO,WEBSTER,TX,USA",
            "coordinates": {
              "lat": 29.533604,
              "lng": -95.136843
            },
            "address": {
              "full": "1310 Jasmine St, Webster, TX 77598, USA",
              "city": "Webster",
              "state": "TX",
              "street": "Jasmine Street",
                    "street_number" :1310
            },
            "operational_contact": {
              "contact_name" : "mr contact",
                    "email" : "hojayevkoch@gmail.com",
                    "phone_number" : "862615986",
                  "notes" : "notes lorem ipsum"
            },
            "scheduling_contact": {
              "contact_name" : "mr contact",
                    "email" : "hojayevkoch@gmail.com",
                    "phone_number" : "862615986",
                  "notes" : "notes lorem ipsum"
            }
          }
        }
      ]
    }
  }
}

and response

{
  "data": {
    "createOffer": {
      "uuid": "933eee0a-8x82-46d6-xxx-018xxxxxxx40",
      "shipper_id": "3"
    }
  },
  "extensions": {
    "lighthouse_subscriptions": {
      "version": 1,
      "channel": null,
      "channels": []
    }
  }
}

to check if working graphql validation, I made mistake on datetime in starttime/endtime and get this:

{
  "errors": [
    {
      "message": "Variable \"$input\" got invalid value {\"open_price\":30,\"shipment\":{\"requested_truck_types\":[\"DRY_VAN\"],\"accessorials\":[\"TWIC_REQUIRED\",\"SHIPPER_REQUIRES_MASK_GLOVES\",\"PPE\"],\"items\":[{\"description\":\"Items description\",\"handling_piece\":{\"piece_type\":\"PALLETS\",\"piece_count\":0},\"units\":{\"unit_type\":\"UNITS\",\"unit_count\":0},\"weight\":{\"weight\":100,\"weight_unit\":\"LB\"}}],\"trailer\":{\"temperature_max\":0,\"temperature_min\":0,\"temperature_unit\":\"F\"},\"short_name\":\"Dem\",\"load_description\":\"load descriotajj adaksdjad\",\"route_distance_miles\":0,\"route_duration_minutes\":0,\"stops\":[{\"appointment_type\":\"ALREADY_MADE\",\"start_time\":\"2021-05-03T00:00:00\",\"type\":\"PICKUP\",\"loading_type\":\"LIVE\",\"location_input\":{\"location_name\":\"HOUSTON\",\"coordinates\":{\"lat\":29.608774,\"lng\":-95.516164},\"address\":{\"place_id\":\"EjQxNDgxMCBGYWlyd2F5IFBpbmVzIERyLCBNaXNzb3VyaSBDaXR5LCBUWCA3NzQ4OSwgVVNB\",\"full\":\"14810 Fairway Pines Dr, Missouri City, TX 77489, USA\",\"city\":\"Missouri City\",\"state\":\"TX\",\"street\":\"Fairway Pines Drive\",\"street_number\":14810},\"operational_contact\":{\"contact_name\":\"mr contact\",\"email\":\"hojayevkoch@gmail.com\",\"phone_number\":\"862615986\",\"notes\":\"notes lorem ipsum\"},\"scheduling_contact\":{\"contact_name\":\"mr contact\",\"email\":\"hojayevkoch@gmail.com\",\"phone_number\":\"862615986\",\"notes\":\"notes lorem ipsum\"}}},{\"appointment_type\":\"TO_BE_MADE\",\"start_time\":\"2021-05-14T05:13:30+00:00\",\"end_time\":\"2021-04-27T17:35:00+00:00\",\"type\":\"DROPOFF\",\"loading_type\":\"LIVE\",\"location_input\":{\"location_name\":\"COSTCO WHO,WEBSTER,TX,USA\",\"coordinates\":{\"lat\":29.533604,\"lng\":-95.136843},\"address\":{\"full\":\"1310 Jasmine St, Webster, TX 77598, USA\",\"city\":\"Webster\",\"state\":\"TX\",\"street\":\"Jasmine Street\",\"street_number\":1310},\"operational_contact\":{\"contact_name\":\"mr contact\",\"email\":\"hojayevkoch@gmail.com\",\"phone_number\":\"862615986\",\"notes\":\"notes lorem ipsum\"},\"scheduling_contact\":{\"contact_name\":\"mr contact\",\"email\":\"hojayevkoch@gmail.com\",\"phone_number\":\"862615986\",\"notes\":\"notes lorem ipsum\"}}}]}}; Expected type DateTimeTz at value.shipment.stops[0].start_time; \"Data missing\"",
      "extensions": {
        "category": "graphql"
      },
      "locations": [
        {
          "line": 1,
          "column": 25
        }
      ]
    }
  ],
  "extensions": {
    "lighthouse_subscriptions": {
      "version": 1,
      "channel": null,
      "channels": []
    }
  }
}

which means all fields I was sending are correct, I think. Maybe requested field types are accepting valid input types from me but causing error while working/parsing them, I don't know, I am struggling with this for almost a week and as you can see two hardcodes (flutter/playground) are the same. My textfields and other inputs are ready but I can't run hardcode first of all:/ btw this is not expired token, for that I got unathorized action error.

Finally we could solve this issue. Issue was occuring on backend while parsing data come from my side. This was the flow of data:

  • user enters data
  • before mutation, flutter parsing data and graphql_flutter mutate
  • then, backend(in our case, php) does fields validation if all are ok, next, if not send validation errors to the client side.
  • after all, server starting storing data on db (here is the key point)

My issue was occuring on last stage, unnecessary model property was sent null, we get to know this by reading logs in laravel.log, so removing that field and migrate db, finally download and using "new" schema.graphql from playground resolved this issue. I hope this will be helpful later:)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM