@Override
    public Stream<MappingField> resolveAndValidateFields(
            boolean isKey,
            List<MappingField> userFields,
            Map<String, String> options,
            InternalSerializationService serializationService
    ) {
        Map<QueryPath, MappingField> fieldsByPath = extractFields(userFields, isKey);

        PortableId portableId = getPortableId(fieldsByPath, options, isKey);
        ClassDefinition classDefinition = serializationService.getPortableContext()
                .lookupClassDefinition(portableId);

        // Fallback option for the case, when the portable objects were not de/serialized yet
        // and user fields were not provided by the user explicitly. In this case we try to
        // manually create a Portable instance and register its ClassDefinition.
        if (userFields.isEmpty() && classDefinition == null) {
            SerializationServiceV1 ss = (SerializationServiceV1) serializationService;
            // Try to create a Portable instance with the default constructor,
            // register its ClassDefinition, and throw object away.
            var tempPortableObj = ss.getPortableSerializer()
                    .createNewPortableInstance(portableId.getFactoryId(), portableId.getClassId());
            if (tempPortableObj != null) {
                try {
                    ss.getPortableContext().lookupOrRegisterClassDefinition(tempPortableObj);
                } catch (Exception e) {
                    // If the default constructor doesn't make Portable fields non-null,we're done:
                    // we can't register the class, so we interrupt the execution with the exception.
                    throw QueryException.error("Cannot create mapping for Portable type. "
                            + "Please, provide the explicit definition for all columns.");
                }
                classDefinition = serializationService.getPortableContext().lookupClassDefinition(portableId);
            }
        }

        return userFields.isEmpty()
                ? resolveFields(isKey, classDefinition)
                : resolveAndValidateFields(isKey, fieldsByPath, classDefinition);
    }
@Test
    @Parameters({
            "true, __key",
            "false, this"
    })
    public void when_typeMismatchBetweenDeclaredAndClassDefinitionField_then_throws(boolean key, String prefix) {
        InternalSerializationService ss = new DefaultSerializationServiceBuilder().build();
        ClassDefinition classDefinition =
                new ClassDefinitionBuilder(1, 2, 3)
                        .addIntField("field")
                        .build();
        ss.getPortableContext().registerClassDefinition(classDefinition);
        Map<String, String> options = ImmutableMap.of(
                (key ? OPTION_KEY_FACTORY_ID : OPTION_VALUE_FACTORY_ID), String.valueOf(classDefinition.getFactoryId()),
                (key ? OPTION_KEY_CLASS_ID : OPTION_VALUE_CLASS_ID), String.valueOf(classDefinition.getClassId()),
                (key ? OPTION_KEY_CLASS_VERSION : OPTION_VALUE_CLASS_VERSION), String.valueOf(classDefinition.getVersion())
        );

        assertThatThrownBy(() -> INSTANCE.resolveAndValidateFields(
                key,
                singletonList(field("field", QueryDataType.VARCHAR, prefix + ".field")),
                options,
                ss
        )).isInstanceOf(QueryException.class)
          .hasMessageContaining("Mismatch between declared and resolved type: field");
    }