Spring Boot: no se puede acceder al controlador REST en localhost (404)

104

Estoy tratando de adaptar el ejemplo del controlador REST en el sitio web de Spring Boot. Desafortunadamente, tengo el siguiente error cuando intento acceder a la localhost:8080/itemURL.

{
  "timestamp": 1436442596410,
  "status": 404,
  "error": "Not Found",
  "message": "No message available",
  "path": "/item"
}

POM:

<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>SpringBootTest</groupId>
   <artifactId>SpringBootTest</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <properties>
      <javaVersion>1.8</javaVersion>
      <mainClassPackage>com.nice.application</mainClassPackage>
      <mainClass>${mainClassPackage}.InventoryApp</mainClass>
   </properties>

   <build>
      <plugins>
         <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.3</version>
            <configuration>
               <source>${javaVersion}</source>
               <target>${javaVersion}</target>
            </configuration>
         </plugin>

         <!-- Makes the Spring Boot app executable for a jar file. The additional configuration is needed for the cmd: mvn spring-boot:repackage 
            OR mvn spring-boot:run -->
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>

            <configuration>
               <mainClass>${mainClass}</mainClass>
               <layout>ZIP</layout>
            </configuration>
            <executions>
               <execution>
                  <goals>
                     <goal>repackage</goal>
                  </goals>
               </execution>
            </executions>
         </plugin>

         <!-- Create a jar with a manifest -->
         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>2.4</version>
            <configuration>
               <archive>
                  <manifest>
                     <mainClass>${mainClass}</mainClass>
                  </manifest>
               </archive>
            </configuration>
         </plugin>
      </plugins>
   </build>

   <dependencyManagement>
      <dependencies>
         <dependency>
            <!-- Import dependency management from Spring Boot. This replaces the usage of the Spring Boot parent POM file. -->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>1.2.5.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
         </dependency>

         <!-- more comfortable usage of several features when developing in an IDE. Developer tools are automatically disabled when 
            running a fully packaged application. If your application is launched using java -jar or if its started using a special classloader, 
            then it is considered a 'production application'. Applications that use spring-boot-devtools will automatically restart whenever files 
            on the classpath change. -->
         <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
         </dependency>
      </dependencies>
   </dependencyManagement>

   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
      </dependency>

      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>

      <dependency>
         <groupId>com.google.guava</groupId>
         <artifactId>guava</artifactId>
         <version>15.0</version>
      </dependency>
   </dependencies>
</project>

Aplicación de inicio:

package com.nice.application;
@SpringBootApplication // same as @Configuration @EnableAutoConfiguration @ComponentScan
public class InventoryApp {
   public static void main( String[] args ) {
      SpringApplication.run( InventoryApp.class, args );
   }
}

Controlador REST:

package com.nice.controller; 
@RestController // shorthand for @Controller and @ResponseBody rolled together
public class ItemInventoryController {
   public ItemInventoryController() {
   }

   @RequestMapping( "/item" )
   public String getStockItem() {
      return "It's working...!";
   }

}

Estoy construyendo este proyecto con Maven. Lo inició como jar (spring-boot: run) y también dentro del IDE (Eclipse).

Registro de la consola:

2015-07-09 14:21:52.132  INFO 1204 --- [           main] c.b.i.p.s.e.i.a.InventoryApp          : Starting InventoryApp on 101010002016M with PID 1204 (C:\eclipse_workspace\SpringBootTest\target\classes started by MFE in C:\eclipse_workspace\SpringBootTest)
2015-07-09 14:21:52.165  INFO 1204 --- [           main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@7a3d45bd: startup date [Thu Jul 09 14:21:52 CEST 2015]; root of context hierarchy
2015-07-09 14:21:52.661  INFO 1204 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Overriding bean definition for bean 'beanNameViewResolver': replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration; factoryMethodName=beanNameViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration.class]] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter; factoryMethodName=beanNameViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter.class]]
2015-07-09 14:21:53.430  INFO 1204 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8080 (http)
2015-07-09 14:21:53.624  INFO 1204 --- [           main] o.apache.catalina.core.StandardService   : Starting service Tomcat
2015-07-09 14:21:53.625  INFO 1204 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.0.23
2015-07-09 14:21:53.731  INFO 1204 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2015-07-09 14:21:53.731  INFO 1204 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1569 ms
2015-07-09 14:21:54.281  INFO 1204 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean        : Mapping servlet: 'dispatcherServlet' to [/]
2015-07-09 14:21:54.285  INFO 1204 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'characterEncodingFilter' to: [/*]
2015-07-09 14:21:54.285  INFO 1204 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2015-07-09 14:21:54.508  INFO 1204 --- [           main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@7a3d45bd: startup date [Thu Jul 09 14:21:52 CEST 2015]; root of context hierarchy
2015-07-09 14:21:54.573  INFO 1204 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2015-07-09 14:21:54.573  INFO 1204 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest)
2015-07-09 14:21:54.594  INFO 1204 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2015-07-09 14:21:54.594  INFO 1204 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2015-07-09 14:21:54.633  INFO 1204 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2015-07-09 14:21:54.710  INFO 1204 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2015-07-09 14:21:54.793  INFO 1204 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
2015-07-09 14:21:54.795  INFO 1204 --- [           main] c.b.i.p.s.e.i.a.InventoryApp          : Started InventoryApp in 2.885 seconds (JVM running for 3.227)
2015-07-09 14:22:10.911  INFO 1204 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring FrameworkServlet 'dispatcherServlet'
2015-07-09 14:22:10.911  INFO 1204 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization started
2015-07-09 14:22:10.926  INFO 1204 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 15 ms

Lo que he probado hasta ahora:

  • Accediendo a la URL con el nombre de la aplicación (InventoryApp)
  • Pon otro @RequestMapping("/")a nivel de clase delItemInventoryController

Por lo que entendí, no necesitaré un contexto de aplicación cuando use Spring Boot. Estoy en lo cierto?

¿Qué más puedo hacer para acceder al método a través de URL?

mchlfchr
fuente
¿Cómo está ejecutando la aplicación? ¿Puede incluir algunos registros?
wjans
Lo intenté por separado a través de Eclipse y con mvn spring-boot: run (como jar). Consulte los registros más arriba (editado)
mchlfchr
Desde el registro de inicio, no parece que esté encontrando su controlador, ¿en qué paquete está su clase de controlador?
MattR
1
Está en un paquete separado. La clase de inicio con el método principal está en "aplicación" mientras que el controlador está en el paquete "controlador". He visto ejemplos (no los de spring.io), que también estaban estructurados de esa manera.
mchlfchr
4
Por defecto, spring-boot buscará componentes en el mismo paquete, o paquetes "debajo" (mismo prefijo) que su clase de aplicación. De lo contrario, debe buscarlos explícitamente, por ejemplo, usando @ComponentScan
MattR

Respuestas:

197

Intente agregar lo siguiente a su clase InventoryApp

@SpringBootApplication
@ComponentScan(basePackageClasses = ItemInventoryController.class)
public class InventoryApp {
...

spring-boot buscará componentes en los paquetes a continuación com.nice.application, por lo que si su controlador está en com.nice.controller, debe buscarlo explícitamente.

MattR
fuente
Tengo los mismos problemas. Intento con el
escaneo de
1
tenga en cuenta que @SpringBootApplicationincluye@Configuration
krzakov
9
Parece más fácil poner la Aplicación en el paquete "raíz", por ejemplo, "org.whatever" y los controladores, servicios en subpaquetes.
insan-e
7
Tengo el mismo problema, pero antes de llegar a esta solución lo encontré ... Leer más. tome su clase de aplicación de arranque de primavera (en la que se define el método principal) un nivel hasta el paquete del controlador ... luego los controladores serán visibles para esto y funcionarán
Tayab Hussain
1
También puede utilizar '@ComponentScan (basePackages = "com.nice.controller")'. El análisis predeterminado del componente comienza en la ruta, donde está la clase de aplicación y el análisis también incluye los paquetes subsidiarios. En ese caso, no es necesario utilizar la anotación @ComponentScan. Lo hace automáticamente. Si tiene más de 1 controlador, es posible tenerlos en diferentes paquetes también, puede encadenarlos. En ese caso, es importante evitar conflictos.
hariprasad
47

Agregando a la respuesta de MattR:

Como se indica en aquí , @SpringBootApplicationinserta automáticamente las anotaciones necesarias: @Configuration, @EnableAutoConfigurationy también @ComponentScan; sin embargo, @ComponentScansolo buscará los componentes en el mismo paquete que la aplicación, en este caso su com.nice.application, mientras que su controlador reside en com.nice.controller. Es por eso que obtienes 404 porque la aplicación no encontró el controlador en el applicationpaquete.

cipley
fuente
5
En caso de que esto no esté completamente claro a partir de la explicación anterior, la clase con la anotación @SpringBootApplication debe estar ARRIBA o en el mismo nivel en la estructura de su directorio que las cosas que le gustaría encontrar. Por ejemplo, tenía com.app.configuration y com.app.controllers. Puse por error mi clase de aplicación en com.app.configuration, y todo lo demás en com.app.configuration funcionó bien, pero no se cargaba nada en com.app.controllers. Moví mi clase de aplicación a com.app y los beans se encontraron en otros lugares y las cosas comenzaron a funcionar. Error de novato para mí.
glaukommatos
2
Agregar @ComponentScan (basePackages = "com.base.package") lo resolvió en mi caso
Shamli
Esto realmente ayuda.
Madhu Tomy
12

Los desarrolladores de SpringBoot recomiendan ubicar su clase de aplicación principal en un paquete raíz por encima de otras clases. El uso de un paquete raíz también permite utilizar la anotación @ComponentScan sin necesidad de especificar un atributo basePackage . Información detallada Pero asegúrese de que exista el paquete raíz personalizado.

torina
fuente
10

La misma respuesta 404 que obtuve después de ejecutar el servicio con el siguiente código

@Controller
@RequestMapping("/duecreate/v1.0")
public class DueCreateController {

}

Respuesta:

{
"timestamp": 1529692263422,
"status": 404,
"error": "Not Found",
"message": "No message available",
"path": "/duecreate/v1.0/status"
}

después de cambiarlo al código siguiente, recibí la respuesta adecuada

@RestController
@RequestMapping("/duecreate/v1.0")
public class DueCreateController {

}

Respuesta:

{
"batchId": "DUE1529673844630",
"batchType": null,
"executionDate": null,
"status": "OPEN"
}
Mahender Ambala
fuente
1
En caso de que otros lectores no lo vean, @Controller->@RestController
Janac Meena
7

Tuve este problema y lo que debes hacer es arreglar tus paquetes. Si descargó este proyecto de http://start.spring.io/, entonces tiene su clase principal en algún paquete. Por ejemplo, si el paquete para la clase principal es: "com.example", entonces y su controlador debe estar en el paquete: "com.example.controller". Espero que esto ayude.

f.trajkovski
fuente
6

Hay 2 métodos para superar esto

  1. Coloque la aplicación de arranque al inicio de la estructura del paquete y coloque todos los controladores en su interior.

    Ejemplo:

    paquete com.spring.boot.app; - Su aplicación de arranque (es decir, Método principal -SpringApplication.run (App.class, args);)

    Descansas el controlador con la misma estructura de paquete Ejemplo: paquete com.spring.boot.app.rest;

  2. Defina explícitamente el controlador en el paquete de arranque.

El método 1 es más limpio.

Mohammed Sarfaraz
fuente
1
spring boot odia que la clase de la aplicación esté bajo algún paquete que no sea el paquete base ... si el paquete base es org.someapp y si lo ponemos bajo org.someapp.app, bombardea ...: - /
Priyank Thakkar
3

Necesita modificar la clase Starter-Application como se muestra a continuación.

@SpringBootApplication

@EnableAutoConfiguration

@ComponentScan(basePackages="com.nice.application")

@EnableJpaRepositories("com.spring.app.repository")

public class InventoryApp extends SpringBootServletInitializer {..........

Y actualice la estructura de los paquetes Controller, Service y Repository como mencioné a continuación.

Ejemplo: REST-Controller

package com.nice.controller; -> Debe modificarse como
package com.nice.application.controller;

Debe seguir la estructura de paquete adecuada para todos los paquetes que se encuentran en el flujo Spring Boot MVC.

Por lo tanto, si modifica las estructuras del paquete del paquete del proyecto correctamente, su aplicación de arranque de primavera funcionará correctamente.

Anjan
fuente
3
EnableAutoConfiguration está incluido en @SpringBootApplication, por lo que es inútil agregarlo.
Sofiane
1

Reemplazar @RequestMapping( "/item" )con @GetMapping(value="/item", produces=MediaType.APPLICATION_JSON_VALUE).

Quizás ayude a alguien.

Ihor Khomiak
fuente
1
me ayudó a reconocer que había escrito en namelugar de valueen el @GetMapping.
vortex.alex
0

Tuve exactamente el mismo error, no estaba dando el paquete base. Dando el paquete base correcto, lo resolvió.

package com.ymc.backend.ymcbe;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@ComponentScan(basePackages="com.ymc.backend")
public class YmcbeApplication {

    public static void main(String[] args) {
        SpringApplication.run(YmcbeApplication.class, args);
    }

}

Nota: sin incluir .controller @ComponentScan (basePackages = "com.ymc.backend.controller") porque tengo muchas otras clases de componentes que mi proyecto no escanea si solo doy .controller

Aquí está mi muestra de controlador:

package com.ymc.backend.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


@RestController
@CrossOrigin
@RequestMapping(value = "/user")
public class UserController {

    @PostMapping("/sendOTP")
    public String sendOTP() {
        return "OTP sent";
    };


}
Nabin Kumar Khatiwada
fuente
0

A veces, la bota de primavera se comporta de manera extraña. Especifiqué a continuación en la clase de aplicación y funciona:

@ComponentScan("com.seic.deliveryautomation.controller")
Amor Kumar
fuente
0

Tengo el problema 404 debido a la sensibilidad a mayúsculas y minúsculas de la URL .

Por ejemplo, se @RequestMapping(value = "/api/getEmployeeData",method = RequestMethod.GET)debe acceder mediante http://www.example.com/api/getEmployeeData. Si lo estamos usando http://www.example.com/api/getemployeedata, obtendremos el error 404.

Nota: http://www.example.comes solo para referencia que mencioné anteriormente. Debe ser su nombre de dominio donde alojó su aplicación.

Después de mucha lucha y aplicar todas las otras respuestas en esta publicación, entendí que el problema es solo con esa URL. Puede ser un problema tonto. Pero me costó 2 horas. Así que espero que ayude a alguien.

Mahendran Sakkarai
fuente
0

para mí, estaba agregando spring-web en lugar de spring-boot-starter-web en mi pom.xml

cuando lo reemplazo de spring-web a spring-boot-starter-web, todo el mapeo se muestra en el registro de la consola.

sakirow
fuente
0

También funciona si usamos lo siguiente:

@SpringBootApplication(scanBasePackages = { "<class ItemInventoryController package >.*" })
Muralidhar
fuente
0

Podría ser que se esté ejecutando algo más en el puerto 8080 y, en realidad, se esté conectando por error.

Definitivamente verifique eso, especialmente si tiene puertos que están mostrando otros servicios que no controla, y están reenviando esos servicios.

Brad Parks
fuente
0

El problema está en la estructura de su paquete. La aplicación Spring Boot tiene una estructura de paquete específica para permitir que el contexto de Spring escanee y cargue varios beans en su contexto.

En com.nice.application es donde está su clase principal y en com.nice.controller, tiene sus clases de controlador.

Mueva su paquete com.nice.controller a com.nice.application para que Spring pueda acceder a sus beans.

Naresh Bhadke
fuente
-1

Puede agregar dentro del POM.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <version>XXXXXXXXX</version>
</dependency>
cemahi
fuente
-2

Coloque su clase springbootapplication en el paquete raíz, por ejemplo, si su servicio, controlador está en el paquete springBoot.xyz, entonces su clase principal debe estar en el paquete springBoot; de lo contrario, no escaneará debajo de los paquetes

ASG
fuente