首页 > 解决方案 > 无法将类型 id 解析为简单类型的子类型 - Spring Boot 中的内部枚举

问题描述

我开发了一个使用 React 作为前端,Spring Boot 作为后端的应用程序。当我尝试将 JSON 数据发送到 Spring Boot 时,出现以下异常:

2018-08-07 22:43:38.721  WARN 41036 --- [io-8080-exec-10] 
.m.m.a.ExceptionHandlerExceptionResolver : 
Resolved exception caused by Handler execution: 
org.springframework.http.converter.HttpMessageNotReadableException: 
JSON parse error: 
Could not resolve type id 'connectionTechnologyName' as a subtype of [simple type, class com.model.ConnectionTechnologyDetails]: 
no such class found; nested exception is com.fasterxml.jackson.databind.exc.InvalidTypeIdException: 
Could not resolve type id 'connectionTechnologyName' as a subtype of [simple type, class com.model.ConnectionTechnologyDetails]: 
no such class found at [Source: (PushbackInputStream); line: 1, column: 515] (through reference chain: com.payload.ConnectionRequest["connectionTechnologyDetails"])

Spring 正在为我的抽象类 ConnectionTechnologyDetails 的假定子类型 ConnectionTechnologyName 搜索类型 ID。所以 Spring 正在寻找一种继承。

抽象类 ConnectionTechnologyDetails 有一个 ConnectionTechnologyName 作为私有属性。ConnectionTechnologyName 的定义进一步是实体 ConnectionTechnologyDetails 的内部枚举。所以没有继承。我不知道有什么问题。

我的 React 应用程序的 JSON 请求由

以下 REST 端点

/**
 * Creates a new connection.
 */
@PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Void> createConnection(@RequestBody ConnectionRequest connectionRequest) {
    logger.warn("ConnectionController: createConnection()");
    try {
        ContactDetails requestContactDetails = connectionRequest.getContactDetails();
        ContactDetails persistedContactDetails = null;
        if (connectionRequest.getContactDetails() != null) {
            ContactDetails tmpContactDetails = new ContactDetails(
                    userRepository.findById(connectionRequest.getUser().getId()).get(),
                    requestContactDetails.getCompany(),
                    requestContactDetails.getAddress(),
                    requestContactDetails.getCity(),
                    requestContactDetails.getState(),
                    requestContactDetails.getCountry(),
                    requestContactDetails.getPostalCode(),
                    requestContactDetails.getCompanyContactPersons(),
                    requestContactDetails.getHlagContactPersons());
            logger.warn("ConnectionController: createConnection() contactDetails created");
            persistedContactDetails = contactDetailsRepository.save(tmpContactDetails);
            logger.warn("ConnectionController: createConnection() conetactDetails saved");
        }
        // business case
        if (connectionRequest.getBusinessCaseName() != null) {
            String requestBusinessCaseName = connectionRequest.getBusinessCaseName();
            logger.warn("ConnectionController: createConnection() businessCaseName got");
        }
        // connection technology details
        if (connectionRequest.getConnectionTechnologyDetails().getConnectionTechnologyName().name() == "SMTP") {
            SMTP requestConnectionDetails = (SMTP) connectionRequest.getConnectionTechnologyDetails();
            SMTP smtp = new SMTP(ConnectionTechnologyDetails.ConnectionTechnologyName.SMTP,
                    requestConnectionDetails.getSenderReceiverIds(),
                    requestConnectionDetails.getSmtp());
            logger.warn("ConnectionController: createConnection() SMTP created");
            SMTP persistedSmtp = connectionTechnologyDetailsRepository.save(smtp);
            logger.warn("ConnectionController: createConnection() SMTP saved");
            Connection newConnection =
                    connectionRepository.save(new Connection(
                            userRepository.findById(connectionRequest.getUser().getId()).get(),
                            contactDetailsRepository.findById(persistedContactDetails.getId()).get(),
                            businessCaseRepository
                                    .findByBusinessCaseName(connectionRequest.getBusinessCaseName()).get()
                            , connectionRequest.getEdiMessageStandard(),
                            connectionTechnologyDetailsRepository.findById(persistedSmtp.getId()).get()));
            return ResponseEntity.created(new URI("api/connections/" + newConnection.getId())).build();

        } else {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
        }
    } catch (URISyntaxException e) {
        return ResponseEntity.status(HttpStatus.CONFLICT).build();
    }
}

@ResponseBody connectionRequest 定义为:

package com.payload;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.model.*;
import com.model.AuditInformation.AuditInformation;
import org.hibernate.annotations.OnDelete;
import org.hibernate.annotations.OnDeleteAction;

import javax.persistence.*;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;

/**
 * Class that represents a connection creation requests message.
 */
public class ConnectionRequest {

    /**
     * Foreign key of the user who created this connection. The user is independent from the connectioin.
     */
    @NotNull
    private ConnectionRequestUser user;


    /**
     * Foreign key for the contact details. They are independent from the connection.
     */
    @NotNull
    private ContactDetails contactDetails;

    /**
     * Business case of connection.
     */
    @NotNull
    private String businessCaseName;

    /**
     * Holds if ANSI or EDIFACT message type.
     */
    @NotNull
    private Connection.EdiMessageStandard ediMessageStandard;

    /**
     * Connection technique used for this connection
     */
    @NotNull
    private ConnectionTechnologyDetails connectionTechnologyDetails;

    public ConnectionRequest(ContactDetails contactDetails, @NotBlank String businessCaseName,
                             Connection.@NotNull EdiMessageStandard ediMessageStandard,
                             ConnectionTechnologyDetails connectionTechnologyDetails,ConnectionRequestUser user) {
        this.user = user;
        this.contactDetails = contactDetails;
        this.businessCaseName = businessCaseName;
        this.ediMessageStandard = ediMessageStandard;
        this.connectionTechnologyDetails = connectionTechnologyDetails;
    }

    public ConnectionRequest() {
    }

    public ConnectionRequestUser getUser() {
        return user;
    }

    public void setUser(ConnectionRequestUser user) {
        this.user = user;
    }

    public ContactDetails getContactDetails() {
        return contactDetails;
    }

    public void setContactDetails(ContactDetails contactDetails) {
        this.contactDetails = contactDetails;
    }

    public String getBusinessCaseName() {
        return businessCaseName;
    }

    public void setBusinessCaseName(String businessCaseName) {
        this.businessCaseName = businessCaseName;
    }

    public Connection.EdiMessageStandard getEdiMessageStandard() {
        return ediMessageStandard;
    }

    public void setEdiMessageStandard(Connection.EdiMessageStandard ediMessageStandard) {
        this.ediMessageStandard = ediMessageStandard;
    }

    public ConnectionTechnologyDetails getConnectionTechnologyDetails() {
        return connectionTechnologyDetails;
    }

    public void setConnectionTechnologyDetails(ConnectionTechnologyDetails connectionTechnologyDetails) {
        this.connectionTechnologyDetails = connectionTechnologyDetails;
    }
}

连接技术详情

import com.fasterxml.jackson.annotation.*;

import javax.persistence.*;
import javax.validation.constraints.NotNull;

/**
 * Represents common connection technology details.
 */
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(discriminatorType = DiscriminatorType.STRING, name = "TECH_TYPE")
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.WRAPPER_OBJECT, property = "@class")
@JsonSubTypes({
        @JsonSubTypes.Type(value = AS2.class, name = "as2"),
        @JsonSubTypes.Type(value = SMTP.class, name = "smtp"),
        @JsonSubTypes.Type(value = FTP.class, name = "ftp"),
        @JsonSubTypes.Type(value = FTPUnsec.class, name = "unsecFtp")
})
public abstract class ConnectionTechnologyDetails {
    /**
     * Unique id.
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    /**
     * To which connection the details belong.
     */
    @OneToOne
    @PrimaryKeyJoinColumn
    @JsonIgnore
    private Connection connection;

    /**
     * Name of the used technology.
     */
    @NotNull
    private ConnectionTechnologyName connectionTechnologyName;

    /**
     * Sender and receiver ids.
     */
    @Embedded
    private SenderReceiverIds senderReceiverIds;

    public enum ConnectionTechnologyName {
        SMTP,
        AS2,
        UNSECURE_FTP,
        SECURE_FTP,
        FTP_SECURE
    }


    /**
     * Constructor
     *
     * @param connectionTechnologyName name of technology
     * @param senderReceiverIds        sender and receiver ids
     */
    public ConnectionTechnologyDetails(ConnectionTechnologyName connectionTechnologyName, SenderReceiverIds senderReceiverIds) {
        this.connectionTechnologyName = connectionTechnologyName;
        this.senderReceiverIds = senderReceiverIds;
    }

    /**
     * COnstructor
     */
    public ConnectionTechnologyDetails() {

    }

    public ConnectionTechnologyName getConnectionTechnologyName() {
        return connectionTechnologyName;
    }

    public void setConnectionTechnologyName(ConnectionTechnologyName connectionTechnologyName) {
        this.connectionTechnologyName = connectionTechnologyName;
    }

    public SenderReceiverIds getSenderReceiverIds() {
        return senderReceiverIds;
    }

    public void setSenderReceiverIds(SenderReceiverIds senderReceiverIds) {
        this.senderReceiverIds = senderReceiverIds;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }


    @Override
    public String toString() {
        return "SenderAndReceiverIds: Name=" + getConnectionTechnologyName().name()
                + " SenderReceiverIds=" + getSenderReceiverIds();
    }
}

我是否必须在 ConnectionTechnologyDetails 中的 ConnectionTechnologyName 属性上设置 @Embedded 注释?还是我必须为公共内部枚举本身设置注释?

标签: javaspring-bootinheritancespring-data-jpainner-classes

解决方案


就我而言...我收到此错误是因为我在代码合并后将 codehaus 与 fastxml jackson 库混合在一起。

一旦我将它们切换到其中一个,它就可以正常工作。


推荐阅读