// Path: service-library/src/main/java/de/codecentric/resilient/dto/BookingServiceRequestDTO.java
// public class BookingServiceRequestDTO {
// 
//     private CustomerResponseDTO customerDTO;
// 
//     private AddressResponseDTO senderAddress;
// 
//     private AddressResponseDTO receiverAddress;
// 
//     public CustomerResponseDTO getCustomerDTO() {
//         return customerDTO;
//     }
// 
//     public void setCustomerDTO(CustomerResponseDTO customerDTO) {
//         this.customerDTO = customerDTO;
//     }
// 
//     public AddressResponseDTO getSenderAddress() {
//         return senderAddress;
//     }
// 
//     public void setSenderAddress(AddressResponseDTO senderAddress) {
//         this.senderAddress = senderAddress;
//     }
// 
//     public AddressResponseDTO getReceiverAddress() {
//         return receiverAddress;
//     }
// 
//     public void setReceiverAddress(AddressResponseDTO receiverAddress) {
//         this.receiverAddress = receiverAddress;
//     }
// 
//     @Override
//     public String toString() {
//         final StringBuilder sb = new StringBuilder("BookingServiceRequestDTO{");
//         sb.append("customerDTO=").append(customerDTO);
//         sb.append(", senderAddress=").append(senderAddress);
//         sb.append(", receiverAddress=").append(receiverAddress);
//         sb.append('}');
//         return sb.toString();
//     }
// }
// 
// Path: service-library/src/main/java/de/codecentric/resilient/dto/BookingServiceResponseDTO.java
// @JsonInclude(JsonInclude.Include.NON_NULL)
// public class BookingServiceResponseDTO extends FallbackAbstractDTO {
// 
//     @JsonProperty(required = true)
//     private ConnoteDTO connoteDTO;
// 
//     @JsonProperty(required = true)
//     private String status;
// 
//     @JsonProperty(required = true)
//     private CustomerDTO customerDTO;
// 
//     @JsonProperty(required = true, value = "service-response-status")
//     private List<ServiceResponseStatus> serviceResponseStatusList;
// 
//     public List<ServiceResponseStatus> getServiceResponseStatusList() {
//         return serviceResponseStatusList;
//     }
// 
//     public void setServiceResponseStatusList(List<ServiceResponseStatus> serviceResponseStatusList) {
//         this.serviceResponseStatusList = serviceResponseStatusList;
//     }
// 
//     public ConnoteDTO getConnoteDTO() {
//         return connoteDTO;
//     }
// 
//     public void setConnoteDTO(ConnoteDTO connoteDTO) {
//         this.connoteDTO = connoteDTO;
//     }
// 
//     public CustomerDTO getCustomerDTO() {
//         return customerDTO;
//     }
// 
//     public void setCustomerDTO(CustomerDTO customerDTO) {
//         this.customerDTO = customerDTO;
//     }
// 
//     public String getStatus() {
//         return status;
//     }
// 
//     public void setStatus(String status) {
//         this.status = status;
//     }
// }


import com.netflix.hystrix.exception.HystrixRuntimeException;
import com.netflix.hystrix.exception.HystrixTimeoutException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.client.RestTemplate;
import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandKey;
import de.codecentric.resilient.dto.BookingServiceRequestDTO;
import de.codecentric.resilient.dto.BookingServiceResponseDTO;

    @Override
    protected BookingServiceResponseDTO run() throws Exception {
        return restTemplate.postForObject("http://booking-service/rest/booking/create", bookingServiceRequestDTO,
            BookingServiceResponseDTO.class);
    }

    @Override
    protected BookingServiceResponseDTO getFallback() {

        if (secondTry) {
            LOGGER.debug(LOGGER.isDebugEnabled() ? "Second Booking Service Call started" : null);

            return new BookingCommand(bookingServiceRequestDTO, restTemplate, false).execute();

        } else {

            BookingServiceResponseDTO bookingServiceResponseDTO = new BookingServiceResponseDTO();
            bookingServiceResponseDTO.setFallback(true);

            if (getExecutionException() != null) {
                Exception exceptionFromThrowable = getExceptionFromThrowable(getExecutionException());
                if (exceptionFromThrowable == null) {
                    bookingServiceResponseDTO.setErrorMsg("Unable to check exception type");

                } else if (exceptionFromThrowable instanceof HystrixRuntimeException) {
                    HystrixRuntimeException hystrixRuntimeException = (HystrixRuntimeException) exceptionFromThrowable;
                    bookingServiceResponseDTO.setErrorMsg(hystrixRuntimeException.getFailureType().name());

                } else if (exceptionFromThrowable instanceof HystrixTimeoutException) {
// Path: service-library/src/main/java/de/codecentric/resilient/dto/BookingServiceRequestDTO.java
// public class BookingServiceRequestDTO {
// 
//     private CustomerResponseDTO customerDTO;
// 
//     private AddressResponseDTO senderAddress;
// 
//     private AddressResponseDTO receiverAddress;
// 
//     public CustomerResponseDTO getCustomerDTO() {
//         return customerDTO;
//     }
// 
//     public void setCustomerDTO(CustomerResponseDTO customerDTO) {
//         this.customerDTO = customerDTO;
//     }
// 
//     public AddressResponseDTO getSenderAddress() {
//         return senderAddress;
//     }
// 
//     public void setSenderAddress(AddressResponseDTO senderAddress) {
//         this.senderAddress = senderAddress;
//     }
// 
//     public AddressResponseDTO getReceiverAddress() {
//         return receiverAddress;
//     }
// 
//     public void setReceiverAddress(AddressResponseDTO receiverAddress) {
//         this.receiverAddress = receiverAddress;
//     }
// 
//     @Override
//     public String toString() {
//         final StringBuilder sb = new StringBuilder("BookingServiceRequestDTO{");
//         sb.append("customerDTO=").append(customerDTO);
//         sb.append(", senderAddress=").append(senderAddress);
//         sb.append(", receiverAddress=").append(receiverAddress);
//         sb.append('}');
//         return sb.toString();
//     }
// }
// 
// Path: service-library/src/main/java/de/codecentric/resilient/dto/BookingServiceResponseDTO.java
// @JsonInclude(JsonInclude.Include.NON_NULL)
// public class BookingServiceResponseDTO extends FallbackAbstractDTO {
// 
//     @JsonProperty(required = true)
//     private ConnoteDTO connoteDTO;
// 
//     @JsonProperty(required = true)
//     private String status;
// 
//     @JsonProperty(required = true)
//     private CustomerDTO customerDTO;
// 
//     @JsonProperty(required = true, value = "service-response-status")
//     private List<ServiceResponseStatus> serviceResponseStatusList;
// 
//     public List<ServiceResponseStatus> getServiceResponseStatusList() {
//         return serviceResponseStatusList;
//     }
// 
//     public void setServiceResponseStatusList(List<ServiceResponseStatus> serviceResponseStatusList) {
//         this.serviceResponseStatusList = serviceResponseStatusList;
//     }
// 
//     public ConnoteDTO getConnoteDTO() {
//         return connoteDTO;
//     }
// 
//     public void setConnoteDTO(ConnoteDTO connoteDTO) {
//         this.connoteDTO = connoteDTO;
//     }
// 
//     public CustomerDTO getCustomerDTO() {
//         return customerDTO;
//     }
// 
//     public void setCustomerDTO(CustomerDTO customerDTO) {
//         this.customerDTO = customerDTO;
//     }
// 
//     public String getStatus() {
//         return status;
//     }
// 
//     public void setStatus(String status) {
//         this.status = status;
//     }
// }


// Path: transport-api-gateway/src/main/java/de/codecentric/resilient/transport/api/gateway/commands/BookingCommand.java
import com.netflix.hystrix.exception.HystrixRuntimeException;
import com.netflix.hystrix.exception.HystrixTimeoutException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.client.RestTemplate;
import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandKey;
import de.codecentric.resilient.dto.BookingServiceRequestDTO;
import de.codecentric.resilient.dto.BookingServiceResponseDTO;


    @Override
    protected BookingServiceResponseDTO run() throws Exception {
        return restTemplate.postForObject("http://booking-service/rest/booking/create", bookingServiceRequestDTO,
            BookingServiceResponseDTO.class);
    }

    @Override
    protected BookingServiceResponseDTO getFallback() {

        if (secondTry) {
            LOGGER.debug(LOGGER.isDebugEnabled() ? "Second Booking Service Call started" : null);

            return new BookingCommand(bookingServiceRequestDTO, restTemplate, false).execute();

        } else {

            BookingServiceResponseDTO bookingServiceResponseDTO = new BookingServiceResponseDTO();
            bookingServiceResponseDTO.setFallback(true);

            if (getExecutionException() != null) {
                Exception exceptionFromThrowable = getExceptionFromThrowable(getExecutionException());
                if (exceptionFromThrowable == null) {
                    bookingServiceResponseDTO.setErrorMsg("Unable to check exception type");

                } else if (exceptionFromThrowable instanceof HystrixRuntimeException) {
                    HystrixRuntimeException hystrixRuntimeException = (HystrixRuntimeException) exceptionFromThrowable;
                    bookingServiceResponseDTO.setErrorMsg(hystrixRuntimeException.getFailureType().name());

                } else if (exceptionFromThrowable instanceof HystrixTimeoutException) {
                    bookingServiceResponseDTO.setErrorMsg(HystrixRuntimeException.FailureType.TIMEOUT.name());