title: Could not resolve type id as a subtype of simple type - inner enum in Spring Boot
body: <p>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:</p>
  
  <pre><code>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"])
  </code></pre>
  
  <p>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.</p>
  
  <p>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.</p>
  
  <p>The JSON request from my React app is handled by the </p>
  
  <p><strong>following REST endpoint</strong>:</p>
  
  <pre><code>/**
   * Creates a new connection.
   */
  @PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
  public ResponseEntity&lt;Void&gt; 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();
      }
  }
  </code></pre>
  
  <p><strong>The @ResponseBody connectionRequest is defined as:</strong></p>
  
  <pre><code>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;
      }
  }
  </code></pre>
  
  <p><strong>ConnectionTehcnologyDetails</strong></p>
  
  <pre><code>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();
      }
  }
  </code></pre>
  
  <p><strong><em>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?</em></strong></p>