How to get Spring REST to lead all endpoints with /v1/ after the domain and port? - spring

How do I make a Spring REST service assign a value after the domain and port, but before the mapped endpoint? For example: http://{domain}/v1/...?
Example:
#RestController
#RequestMapping("home")
public class HomeController {
#RequestMapping("number")
public ResponseEntity getNumber() {
return ResponseEntity.ok(1);
}
}
curl http://localhost:8080/v1/home/number ~ 1
Also, is there a name for what I'm trying to achieve?

Assuming you're using Spring Data Rest, you can configure it in the RepositoryRestConfiguration #Configuration class like so:
public class SDRConfig extends RepositoryRestMvcConfiguration {
#Override
public RepositoryRestConfiguration config() {
RepositoryRestConfiguration config = super.config();
config.setBasePath("/v1");
return config;
}
}
Alternatively, with Spring Boot I believe it's
spring.data.rest.baseUri=api

Related

Spring Boot actuator trigger method when endpoint called

I am using this spring boot actuator endpoint "actuator/health/readiness". How can I run some methods when this endpoint is hit?
If I create my own controller with the same endpoint naming what will happen?
Thanks
Works in spring 2.7.2
public class CustomReadinessStateHealthIndicator extends ReadinessStateHealthIndicator {
public CustomReadinessStateHealthIndicator(ApplicationAvailability availability) {
super(availability);
}
#Override
public Health getHealth(boolean includeDetails) {
//YOUR CODE
return super.getHealth(includeDetails);
}
}
#AutoConfiguration(before = {AvailabilityHealthContributorAutoConfiguration.class})
public class Configuration {
#Bean("readinessStateHealthIndicator")
#ConditionalOnMissingBean(name = "readinessStateHealthIndicator")
public ReadinessStateHealthIndicator customReadiness(ApplicationAvailability applicationAvailability) {
return new CustomReadinessStateHealthIndicator(applicationAvailability);
}
}

Feign Client Custom Configuration Does Not Take Effect

I use feign in my project. I created a custom configuration but it is overridden by default configuration. Here are the steps:
SpringBootApplication.java
#SpringBootApplication
#EnableDiscoveryClient
#EnableFeignClients
public class MyApplication {}
FeignConfiguration.java
#RequiredArgsConstructor
public class FeignConfiguration{
private final MyConfigurationProperties myConfigProperties;
#Bean
public MetaDataRestClient metaDataRestClient(#Qualifier("metaDataHttpClient") okhttp3.OkHttpClient metaDataHttpClient) {
return Feign.builder()
.retryer(Retryer.NEVER_RETRY)
.client(new OkHttpClient(metaDataHttpClient))
.encoder(new JacksonEncoder(XML_MAPPER))
.decoder(new JacksonDecoder(XML_MAPPER))
.contract(new SpringMvcContract())
.logger(new Slf4jLogger(MetaDataRestClient.class))
.logLevel(Logger.Level.FULL)
.target(MetaDataRestClient.class, myConfigProperties.getMetadata().getEndpoint());
}
#Primary
#Bean(name = "metaDataHttpClient")
public okhttp3.OkHttpClient metaDataHttpClientWithProxy() {
return OkHttpUtil.createNewHttpClientBuilderWithProxy(myConfigProperties.getMetadata().getFeignClient().getConnectTimeout(),
myConfigProperties.getMetadata().getFeignClient().getReadTimeout()).build();
}
MetaDataRestClient.java
#FeignClient(name = "metaDataRestClient", url = "https://myurl.net", configuration = FeignConfiguration.class)
public interface MetaDataRestClient {
#Headers("Content-Type: text/xml")
#GetMapping("/metadata")
public EntityDescriptor getMetadaData();
}
I see that the metaDataRestClient bean is triggered on startup, but when I dig into feign library code, I see that this method is triggered twice: first time with my custom OkHttpClient, and second time with somehing called org.springframework.cloud.sleuth.instrument.web.client.feign.LazyClient. So my custom OkHttpClient is overridden by this lazy client.
Here is the related Feign library code that is being triggered twice:
FeignBuilder.java
public Builder client(Client client) {
this.client = client;
return this;
}
I do not have any feign configurationn in my application.yaml file. What could be the reason for that?
Thanks.

RSocket with Webflux router

I have an application with Spring boot webflux and exposing endpoints as below.
#Configuration
public class BusinessServiceConfiguration {
#Autowired
private final RequestHandler reqHandler;
#Bean
public RouterFunction<ServerResponse> createUser() {
return route(POST("/api/v1/user/create").and(contentType(APPLICATION_JSON)), reqHandler::createUser);
}
}
Came across RSocket and it is promising. Planning to move to RSocket down the line.
Exposing end point with RSocket,
#Controller
public class RSocketController {
#Autowired
private final RequestService reqService;
#MessageMapping("/api/v1/user/create")
public Mono<String> createuser() {
return reqService.createUser .....
}
}
Here, the way we expose API is totally different b/w Webflux and RSocket and it need some effort.
Is there anyway to just add RSocket without changing the way we expose end points?

AutoConfigure RestController Spring Boot

I have tried to find documentation on how to manually configure a RestController (i.e in a Configuation class). That means without using the RestController annotation. Considering all the other annotations, like mapping, pathvariables etc. is at all possible?
A controller is essentially a component with a request mapping. See RequestMappingHandlerMapping.
#Override
protected boolean isHandler(Class<?> beanType) {
return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
}
If you want to instantiate a "rest controller" through configuration, you can probably do so via the following:
#Configuration
public class MyConfiguration {
#Bean
public MyController() {
return new MyController();
}
}
#ResponseBody
public class MyController {
#RequestMapping("/test")
public String someEndpoint() {
return "some payload";
}
}
But I don't think you'll be able to configure the request mappings (path variables, etc) in the configuration though; at least I haven't seen an example nor figured out how.

Using #FeignClient with OAuth2Authentication in Javaclient

I would like to use a #FeignClient in a simple spring boot application (CommandLineRunner) to call a microservice endpoint. How can I provide an OAuth2Authentication to call a protected endpoint like helloUser() ?
#FeignClient(name = "sampleService", contextId = "greetingService")
public interface GreetingService {
#GetMapping("/hello-anonymous")
String helloAnonymous();
#GetMapping("/hello-user")
#Secured({ Role.USER })
String helloUser();
#GetMapping("/hello-admin")
#Secured({ Role.ADMIN })
String helloAdmin();
}
You can use Feign RequestInterceptor to pass the auth header downstream:
public class FeignRequestInterceptor implements RequestInterceptor {
#Override
public final void apply(RequestTemplate template) {
template.header("Authorization", "foo token");
}
}
This way all the feign calls will be provisioned with an auth header.

Resources