Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

spring.data.rest.base-path not working #19163

Closed
judos opened this issue Nov 27, 2019 · 2 comments
Closed

spring.data.rest.base-path not working #19163

judos opened this issue Nov 27, 2019 · 2 comments
Labels
for: stackoverflow A question that's better suited to stackoverflow.com status: invalid An issue that we don't feel is valid

Comments

@judos
Copy link

judos commented Nov 27, 2019

When I use the application property spring.data.rest.base-path=/api my rest controller is still accessible under the path /.

Version: 2.2.1.RELEASE

Doing the request (wrong path):

curl localhost:8080/hello
Greetings from Spring Boot!

Request actually wanted path with rest base-path config:

curl localhost:8080/api/hello
{"timestamp":"2019-11-27T15:10:59.449+0000","status":404,"error":"Not Found","message":"No message available","path":"/api/hello"}

My application.properties (is at correct place, otherwise db connection wouldn't work, which I had earlier when setting up project)

# ===============================
# = Logging
# ===============================

spring.main.banner-mode=off
spring.devtools.restart.log-condition-evaluation-delta=false

logging.level.root=WARN
logging.level.org.springframework.boot.web.embedded.tomcat.TomcatWebServer=INFO
# only show actual version and migrations done
logging.level.org.flywaydb.core=WARN
logging.level.org.flywaydb.core.internal.command.DbMigrate=INFO
# if you want to hide "JPA does not support custom isolation levels, so locks may not be taken when launching Jobs"
# logging.level.org.springframework.boot.autoconfigure.batch.JpaBatchConfigurer=ERROR

# make sure to show blocked logins when e.g. no authorization is available for the user
# logging.level.org.springframework.security.core.userdetails.jdbc=DEBUG
# logging.level.org.flywaydb.core.Flyway=ERROR

# support colored logs if possible
spring.output.ansi.enabled=DETECT
logging.pattern.console=%gray(%d{YYYY-MM-dd HH:mm:ss}) %highlight(%-5p) %clr(%-30.30logger{30}){gray} %clr(:){red} %clr(%m){faint}%n
# thread logging pattern: %clr([%8.15t]){cyan} 

# ===============================
# = Actuator
# ===============================

management.endpoints.enabled-by-default=false
management.endpoint.info.enabled=true
management.endpoint.health.enabled=true
management.endpoint.health.show-details=always
management.endpoints.web.exposure.include=health,info
management.endpoints.web.base-path=/api/actuator/

# ===============================
# = File uploads / downloads
# ===============================

spring.servlet.multipart.max-file-size=100MB
spring.servlet.multipart.max-request-size=100MB

# ===============================
# = Static resources
# ===============================

#
spring.data.rest.base-path=/api/
spring.mvc.static-path-pattern=/**

# ===============================
# = DATA SOURCE
# ===============================

# Connection url for the database
spring.datasource.url=jdbc:mysql://localhost:3306/test?allowPublicKeyRetrieval=true&useSSL=false
spring.flyway.url=jdbc:mysql://localhost:3306/test?allowPublicKeyRetrieval=true&useSSL=false
spring.flyway.schemas=test

# Username and password
spring.datasource.username=test
spring.flyway.user=test
spring.datasource.password=
spring.flyway.password=
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver


# Keep the connection alive if idle for a long time (needed in production)
spring.datasource.testWhileIdle=true
spring.datasource.validationQuery=SELECT 1

# ===============================
# = JPA / HIBERNATE
# ===============================

# Use spring.jpa.properties.* for Hibernate native properties (the prefix is
# stripped before adding them to the entity manager).

# Show or not log for each sql query
spring.jpa.show-sql=false

# https://stackoverflow.com/questions/30549489/what-is-this-spring-jpa-open-in-view-true-property-in-spring-boot
# if true makes EntityManager available for as long as a web request is processed 
# to allow lazy loading after first db query.
spring.jpa.open-in-view=true

# Hibernate ddl auto (create, create-drop, update, validate): with "update" the database
# schema will be automatically updated accordingly to java entities found in
# the project
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=validate

# Naming strategy
spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.ImprovedNamingStrategy

# Allows Hibernate to generate SQL optimized for a particular DBMS
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect

My build.gradle:

buildscript {
	repositories {
		jcenter()
		mavenCentral()
	}
	dependencies {
		classpath('org.springframework.boot:spring-boot-gradle-plugin:2.2.1.RELEASE')
		//TODO: check if we should use newer version
		classpath('cz.habarta.typescript-generator:typescript-generator-gradle-plugin:2.3.415')
	}
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
apply plugin: 'cz.habarta.typescript-generator'

repositories {
	mavenCentral()
}

configurations.all {
	exclude group: 'org.slf4j', module: 'slf4j-log4j12'
}

dependencies {
	compile 'org.springframework.boot:spring-boot-starter-web:2.2.1.RELEASE'
	compile 'org.springframework.boot:spring-boot-starter-data-jpa:2.2.1.RELEASE'
	compile 'org.springframework.boot:spring-boot-starter-actuator:2.2.1.RELEASE'
	compile 'mysql:mysql-connector-java:8.0.18'
	compile 'com.querydsl:querydsl-jpa:4.2.1'
	compile 'com.querydsl:querydsl-apt:4.2.1:jpa'
	compile 'com.google.code.gson:gson:2.8.6'
	compile 'org.flywaydb:flyway-core:6.0.8'
	compileOnly 'org.springframework.boot:spring-boot-devtools:2.2.1.RELEASE'

	// https://mvnrepository.com/artifact/org.apache.commons/commons-text
	compile 'org.apache.commons:commons-text:1.8'
	// https://mvnrepository.com/artifact/org.apache.commons/commons-lang3
	compile 'org.apache.commons:commons-lang3:3.9'
	// https://mvnrepository.com/artifact/org.apache.commons/commons-csv
	compile 'org.apache.commons:commons-csv:1.7'
	// https://mvnrepository.com/artifact/org.apache.commons/commons-collections4/4.3
	compile 'org.apache.commons:commons-collections4:4.4'

	testCompile 'junit:junit'
	testCompile 'org.springframework.boot:spring-boot-starter-test'
}

Main:

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class Application {

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

    @Bean
    public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
        return args -> {
            // manually initialize something
        };
    }

}

Rest Controller

import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;

@RestController
public class HelloController {

    @RequestMapping("/hello")
    public String index() {
        return "Greetings from Spring Boot!";
    }

}

I found an older ticket for spring 1.3.5 where this was broken as well: #6250

Does anyone know why this is not working?

For now I have to modify every controller and add this annotation at the beginning:
@RequestMapping("api")

Best regards

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Nov 27, 2019
@bclozel
Copy link
Member

bclozel commented Nov 27, 2019

I think this is the expected behavior, as the spring.data.rest.base-path property is meant for Spring Data REST, which is about exposing Spring Data repositories as REST resources.

There are several ways to achieve that. You could prefix everything with a path (controller and static resources) by using server.servlet.context-path. If you only wish to add a route prefix to all/some controllers, you can implement a WebMvcConfigurer class and its method that customizes the PathMatchConfigurer. The PathMatchConfigurer#addPathPrefix(String, Predicate<Class<?>>) allows you to configure such a prefix as you wish.

For further questions, please use StackOverflow. Thanks!

@bclozel bclozel closed this as completed Nov 27, 2019
@bclozel bclozel added for: stackoverflow A question that's better suited to stackoverflow.com status: invalid An issue that we don't feel is valid and removed status: waiting-for-triage An issue we've not yet triaged labels Nov 27, 2019
@judos
Copy link
Author

judos commented Nov 28, 2019

Oh ok, then I actually mistook this config. I don't actually want to expose the Repositories automatically.
I don't want to change the path of static resources, so context-path config doesn't work for me.
The WebMvcConfigurer options sounds best. I tried and the following approach worked for me:

@Configuration
public class ApiBasePathConfiguration implements WebMvcConfigurer {
    private Logger logger = LoggerFactory.getLogger(getClass());

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        configurer.addPathPrefix("/api", (clazz)->true);
    }
}

Thanks for clarification!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
for: stackoverflow A question that's better suited to stackoverflow.com status: invalid An issue that we don't feel is valid
Projects
None yet
Development

No branches or pull requests

3 participants