Spring Boot v1.5.3.RELEASE with Jersey 2 return 404 to all requests JSON

I have and application with Spring Boot and Jersey. Here the pom.xml:

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>cat.amb.parkride</groupId>
    <artifactId>parkride</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>parkride</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.3.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.wordnik</groupId>
            <artifactId>swagger-annotations_2.10</artifactId>
            <version>1.3.0</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.6.1</version>
        </dependency>
        <!-- Mandatory dependencies for using Spock -->
        <dependency>
            <groupId>org.spockframework</groupId>
            <artifactId>spock-core</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.codehaus.groovy</groupId>
            <artifactId>groovy-all</artifactId>
        </dependency>
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib-nodep</artifactId>
            <version>3.2.4</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.objenesis</groupId>
            <artifactId>objenesis</artifactId>
            <version>2.5.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.hamcrest</groupId>
            <artifactId>hamcrest-core</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- Mandatory dependencies for using Spock -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.5</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.4</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jersey</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <!-- Mandatory dependencies for using Spock -->
            <plugin>
                <groupId>org.codehaus.gmavenplus</groupId>
                <artifactId>gmavenplus-plugin</artifactId>
                <version>1.5</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>testCompile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.18.1</version>
                <configuration>
                    <useFile>false</useFile>
                    <includes>
                        <include>**/*Spec.java</include>
                    </includes>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-deploy-plugin</artifactId>
                <version>2.8.2</version>
                <configuration>
                    <skip>true</skip>
                </configuration>
            </plugin>
            <!-- Mandatory dependencies for using Spock -->
        </plugins>
    </build>

</project>

This is the main class:

package cat.amb.parkride;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

import cat.amb.parkride.adapter.rest.BasicRest;
import cat.amb.parkride.config.JerseyConfig;

@SpringBootApplication
//@ComponentScan(basePackages = {"cat.amb.parkride", "cat.amb.parkride.adapter.rest"})
public class ParkRideApplication {
    private final Logger logger = LoggerFactory.getLogger(ParkRideApplication.class);

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

This is my configuration for Jersey:

package cat.amb.parkride.config;

import javax.ws.rs.ApplicationPath;

import org.glassfish.jersey.filter.LoggingFilter;
import org.glassfish.jersey.server.ResourceConfig;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import com.fasterxml.jackson.databind.ObjectMapper;

import cat.amb.parkride.adapter.rest.AuthRest;
import cat.amb.parkride.adapter.rest.TestRest;
import cat.amb.parkride.adapter.rest.UserRest;

@Configuration
@Component
@ApplicationPath("/parkride/rest")
public class JerseyConfig extends ResourceConfig {

    public JerseyConfig(ObjectMapper objectMapper) {
        registerEndPoints();
        register(LoggingFilter.class);
    }

    private void registerEndPoints() {
        register(TestRest.class);
        register(AuthRest.class);
        register(UserRest.class);       
    }
}

And this is the Rest class:

package cat.amb.parkride.adapter.rest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
@Consumes({ MediaType.APPLICATION_JSON + "; charset=UTF-8" })
@Produces({ MediaType.APPLICATION_JSON + "; charset=UTF-8" })
public class TestRest extends BasicRest {
    private final Logger logger = LoggerFactory.getLogger(TestRest.class);

    @Path("/test/v1/test")
    @GET
    public Response test() throws Exception {
        logger.debug("Estamos dentro!!");
        return getResponse("OK", null, HttpServletResponse.SC_OK);
    }

    @Path("/parkride/rest/test/v1/test")
    @GET
    public Response test2() throws Exception {
        logger.debug("Estamos dentro!!");
        return getResponse("OK", null, HttpServletResponse.SC_OK);
    }
}

The structure of packages are:

cat.amb.parkride adapter dao rest TestRest.java commons config domain ParkRideApplication.java

In every call to this methods i can see in log:

2017-05-08 18:37:42.110  INFO 8412 --- [  restartedMain] cat.amb.parkride.ParkRideApplication     : Started ParkRideApplication in 2.219 seconds (JVM running for 70.125)
2017-05-08 18:37:45.275  INFO 8412 --- [nio-8080-exec-1] o.glassfish.jersey.filter.LoggingFilter  : 1 * Server has received a request on thread http-nio-8080-exec-1
1 > GET http://localhost:8080/parkride/rest/test/v1/test
1 > accept: */*
1 > accept-encoding: gzip, deflate, br
1 > accept-language: es,en;q=0.8,ca;q=0.6
1 > cache-control: no-cache
1 > connection: keep-alive
1 > content-type: application/json; charset=UTF-8
1 > host: localhost:8080
1 > postman-token: 34696faf-d1e2-fc6b-28d7-b2db672f2578
1 > user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3091.0 Safari/537.36

2017-05-08 18:37:45.275  INFO 8412 --- [nio-8080-exec-1] o.glassfish.jersey.filter.LoggingFilter  : 1 * Server responded with a response on thread http-nio-8080-exec-1
1 < 404

2017-05-08 18:37:45.276  INFO 8412 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring FrameworkServlet 'dispatcherServlet'
2017-05-08 18:37:45.276  INFO 8412 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization started
2017-05-08 18:37:45.285  INFO 8412 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 9 ms

But I can enter in to the REST method, seems like the Jersey takes the request but don't execute the method

Upvotes: 1

Views: 1795

Answers (1)

Paul Samsotha
Paul Samsotha

Reputation: 209102

Jersey resource classes needed to annotated with @Path. That's the only way they are known to be root resources, even if you register them. They still ned this annotation. Your TestRest does not have this. If it's on the BaseRest class, that won't work. It needs to be on the concrete implementation that is registered.

In regards to how the final routes will be constructed is based on a combination of the @ApplicationPath, the @Path on the resource class and the @Path on the resource method. If the resource method has no @Path, then the route will be that of the resource class' path. For example

@ApplicationPath("/api")
public class AppConfig extends ResourceConfig {}

@Path("/animals")
public class AnimalsResource {

    @GET
    public List<Animal> getAll() {}

    @Path("/{id}")
    pubic Animal getOne(@PathParam("id") int id) {}
}
  • GET /api/animals goes to AnimalsResource.getAll
  • GET /api/animals/1 goes to AnimalsResource.getOne

Upvotes: 2

Related Questions