3
respostas

retrofit2.HttpException: HTTP 404

Bom dia a todos Eu tava seguindo o código da aula, quando eu fui rodar o teste de Requisições assíncronas, com este link no Postman:

http://localhost:8080/cars/inventory?model=gol

deu essa exceção:

retrofit2.HttpException: HTTP 405 
    at retrofit2.KotlinExtensions$await$2$2.onResponse(KotlinExtensions.kt:53) ~[retrofit-2.9.0.jar:na]
    at io.github.resilience4j.retrofit.RetrofitCircuitBreaker$CircuitBreakingCall$1.onResponse(RetrofitCircuitBreaker.java:94) ~[resilience4j-retrofit-1.7.1.jar:1.7.1]
    at retrofit2.OkHttpCall$1.onResponse(OkHttpCall.java:161) ~[retrofit-2.9.0.jar:na]
    at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:519) ~[okhttp-4.9.3.jar:na]
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) ~[na:na]
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) ~[na:na]
    at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]

Eu queria saber qual seria o possível erro em relação à isso. Vou deixar os códigos da aula:

import br.com.car.domain.http.CarHttp
import org.springframework.stereotype.Service
import retrofit2.http.GET
import retrofit2.http.Query

@Service
interface CarHttpService {

    @GET("cars-inventory")
    suspend fun getByModel(@Query("model") model: String): List<CarHttp>
}
import br.com.car.adapters.http.CarHttpService
import br.com.car.core.converter.CarHttpToModelConverter
import br.com.car.domain.model.Car
import br.com.car.domain.ports.CarRepository
import br.com.car.domain.ports.CarService
import kotlinx.coroutines.coroutineScope
import org.springframework.cache.annotation.CacheEvict
import org.springframework.cache.annotation.Cacheable
import org.springframework.stereotype.Service

@Service
internal class CarService(
    private val carRepository: CarRepository,
    private val carHttpService: CarHttpService
) : CarService {
//outros códigos ocultos
    override suspend fun listByInventory(model: String) = coroutineScope {
        carHttpService
            .getByModel(model)
            .let(CarHttpToModelConverter::toModel)
    }
}
import br.com.car.domain.model.Car
import br.com.car.domain.ports.CarService
import kotlinx.coroutines.runBlocking
import org.springframework.web.bind.annotation.*

@RestController
@RequestMapping("/cars")
class CarResource(
    private val carService: CarService
) {
//outros códigos ocultos
    @GetMapping("/inventory")
    fun listByInventory(@RequestParam model: String) = runBlocking {
        carService.listByInventory(model)
    }
}
import br.com.car.domain.model.Car

interface CarService {

    fun list(model: String?): List<Car>
    fun save(car: Car): Int
    fun update(car: Car, id: Long): Int
    fun findById(id: Long): Car
    suspend fun listByInventory(model:String): List<Car>?
}

Vou também deixar a classe de configuração do Retrofit:

import br.com.car.adapters.configuration.circuitbreaker.CircuitBreakerConfiguration
import br.com.car.adapters.http.CarHttpService
import io.github.resilience4j.retrofit.CircuitBreakerCallAdapter
import okhttp3.OkHttpClient
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory

@Configuration
class CarHttpConfiguration(
    private val circuitBreakerConfiguration: CircuitBreakerConfiguration
) {

    private companion object {
        const val BASE_URL = "http://localhost:8080/"
    }

    private fun buildClient() = OkHttpClient.Builder().build()

    private fun buildRetrofit() = Retrofit.Builder()
        .addCallAdapterFactory(CircuitBreakerCallAdapter.of(circuitBreakerConfiguration.getCircuitBreaker()))
        .baseUrl(BASE_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .client(buildClient())
        .build()

    @Bean
    fun carHttpService(): CarHttpService = buildRetrofit().create(CarHttpService::class.java)
}

PS: eu tive outro problema relacionado ao retrofit na aula 1, postei aqui no fórum e no discord da alura e ainda não foi resolvido

Ps2: eu testei o código da aula que está no github e encontrei o mesmo problema

Ps3: a única alteração foi trocar o link do arquivo do retrofit, que no original estava:

const val BASE_URL = "http://ec2-18-215-156-13.compute-1.amazonaws.com:8080"

que gera essa exceção:

java.net.ConnectException: Failed to connect to ec2-18-215-156-13.compute-1.amazonaws.com/18.215.156.13:8080

por esse endereço:

 const val BASE_URL = "http://localhost:8080/"
3 respostas

Vou deixar meu pom.xml (parte 1) aqui para consulta também:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.1</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.br.car</groupId>
    <artifactId>car-service</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>car-service</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>17</java.version>
        <kotlin.version>1.6.21</kotlin.version>
        <testcontainers.version>1.17.2</testcontainers.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.module</groupId>
            <artifactId>jackson-module-kotlin</artifactId>
        </dependency>
        <dependency>
            <groupId>org.flywaydb</groupId>
            <artifactId>flyway-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.flywaydb</groupId>
            <artifactId>flyway-mysql</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-reflect</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-stdlib-jdk8</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.testcontainers</groupId>
            <artifactId>junit-jupiter</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.testcontainers</groupId>
            <artifactId>mysql</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/io.mockk/mockk -->
        <dependency>
            <groupId>io.mockk</groupId>
            <artifactId>mockk</artifactId>
            <version>1.12.5</version>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.squareup.retrofit2/retrofit -->
        <dependency>
            <groupId>com.squareup.retrofit2</groupId>
            <artifactId>retrofit</artifactId>
            <version>2.9.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.squareup.retrofit2/converter-gson -->
        <dependency>
            <groupId>com.squareup.retrofit2</groupId>
            <artifactId>converter-gson</artifactId>
            <version>2.9.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/io.github.resilience4j/resilience4j-circuitbreaker -->
        <dependency>
            <groupId>io.github.resilience4j</groupId>
            <artifactId>resilience4j-circuitbreaker</artifactId>
            <version>2.0.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/io.github.resilience4j/resilience4j-retrofit -->
        <dependency>
            <groupId>io.github.resilience4j</groupId>
            <artifactId>resilience4j-retrofit</artifactId>
            <version>1.7.1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core -->
        <dependency>
            <groupId>org.jetbrains.kotlinx</groupId>
            <artifactId>kotlinx-coroutines-core</artifactId>
            <version>1.6.4</version>
            <type>pom</type>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.testcontainers</groupId>
                <artifactId>testcontainers-bom</artifactId>
                <version>${testcontainers.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.jetbrains.kotlinx</groupId>
                <artifactId>kotlinx-coroutines-bom</artifactId>
                <version>1.6.4</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

pom.xml(parte 2):


    <build>
        <sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
        <testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.jetbrains.kotlin</groupId>
                <artifactId>kotlin-maven-plugin</artifactId>
                <configuration>
                    <args>
                        <arg>-Xjsr305=strict</arg>
                    </args>
                    <compilerPlugins>
                        <plugin>spring</plugin>
                    </compilerPlugins>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.jetbrains.kotlin</groupId>
                        <artifactId>kotlin-maven-allopen</artifactId>
                        <version>${kotlin.version}</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </build>

    <profiles>
        <profile>
            <id>dev</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <properties>
                <activatedProperties>dev</activatedProperties>
            </properties>
        </profile>
        <profile>
            <id>prod</id>
            <properties>
                <activatedProperties>prod</activatedProperties>
            </properties>
        </profile>
    </profiles>

</project>

Olá, Murilo!

Pelo erro que você está recebendo, "retrofit2.HttpException: HTTP 405", parece que você está tentando fazer uma requisição HTTP do tipo GET para um endpoint que só aceita requisições do tipo POST. Isso pode ser confirmado pela mensagem "HTTP 405" que é retornada pelo servidor.

No seu código, você está fazendo a requisição GET para o endpoint "/cars/inventory?model=gol". Verifique se esse endpoint está configurado corretamente no seu servidor e se ele aceita requisições do tipo GET.

Além disso, verifique se você está utilizando a anotação correta no seu código para definir o tipo de requisição. No arquivo "CarResource.kt", você está utilizando a anotação "@GetMapping" para definir a rota "/inventory" e o método "listByInventory". Certifique-se de que essa anotação está correta e que corresponde ao tipo de requisição que você está fazendo.

Se você já verificou esses pontos e o erro persiste, pode ser que haja algum problema na configuração do Retrofit ou na comunicação com o servidor. Verifique se a URL base está correta no arquivo "CarHttpConfiguration.kt" e se todas as dependências do Retrofit estão configuradas corretamente.

Espero que essas sugestões possam te ajudar a resolver o problema. Se tiver mais alguma dúvida, é só me dizer! Espero ter ajudado e bons estudos!