Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Could not resolve type id as a subtype of simple type - inner enum in Spring Boot

I've developed an application with React as front end and Spring Boot as back end. When I'm trying to send my JSON data to Spring Boot, I got the following exception:

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 is searching for the type id for the assumed subtype ConnectionTechnologyName of my abstract class ConnectionTechnologyDetails. So Spring is searching for a sort of inheritance.

The abstact class ConnectionTechnologyDetails has a ConnectionTechnologyName as private attribute. The definition of ConnectionTechnologyName is furthermore an inner enum of the entitiy ConnectionTechnologyDetails. So there is no inheritance. I don't know what's the problem.

The JSON request from my React app is handled by the

following REST endpoint:

/**
 * 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();
    }
}

The @ResponseBody connectionRequest is defined as:

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;
    }
}

ConnectionTehcnologyDetails

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();
    }
}

Do I have to set an @Embedded annotation on ConnectionTechnologyName attribute in ConnectionTechnologyDetails? Or do i have to set an annotation to the public inner enum itself?

like image 903
Taskmanager Avatar asked Jan 23 '26 23:01

Taskmanager


1 Answers

In my case... I was getting this error because I was mixing codehaus with fasterxml jackson libraries after a code merge.

Once I switched them to one or the other, it worked fine.

like image 66
Nicholas DiPiazza Avatar answered Jan 26 '26 14:01

Nicholas DiPiazza