How to get Application properties configuration into Annotation as parameter - spring

I want to use #CrossOrigin annotation on my RestController in my Spring Boot application and set origins parameter with the values from application.properties file.
#CrossOrigin(origins = {"${app.cors.origins}"})
public class SomeController(){
//
//
}
I set the property in my application.properties file like
app.cors.origins =http://www.google.com,http://localhost:8001
However that doesn't work as a cross origin request from http://localhost:8001 to my app fails with CORS error on the browser.
Am I missing something on setting the property?
Update : Problem is to set origins as a string array from the value of application property entry. When I hardcode the urls in origin, it works.
Thanks

If you want to use application.properties to set origins of CORS then this is the solution.
#Configuration
public class WebMvcConfig implements WebMvcConfigurer {
#Value("${app.cors.origins}")
private String corsAllowedOrigins;
#Value("${app.cors.methods}")
private String corsAllowedMethods;
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins(corsAllowedOrigins)
.allowedMethods(corsAllowedMethods);
}
application.properties
app.cors.origins=http://www.google.com,http://localhost:8001
app.cors.methods=GET,OPTIONS

I'm also working on this issue, I found another post mentioned about controller level parameter annotation for Cors. I haven't try it yet. share it with you:
Create your custom annotation and annotate the API with that.
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.METHOD})
#CrossOrigin
public #interface CrossOriginsList {
public String[] crossOrigins() default {
"http://domain1.com", "http://domain1.com"
"http://domain1.com", "http://domain1.com"
// Pass as many as you want
};
}
And now Annotate your API with this custom Annotation
#CrossOriginsList
public String methodName() throws Exception
{
//Business Logic
}

Related

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.

best way to dynamically populate .js properties from spring boot runtime application.properties?

tldr
How to best "put" runtime application.properties values from a spring boot app in a javascript file
[Admittedly this is probably a stupid question for the experienced spring dev...so please share how to solve this problem "the spring way"]
Context
We have tiny app which a front-end developer put together and "threw over the wall"..It defines a properties file settings.js:
var SERVERROOT = 'http://solr:8983/solr/operations/select/';
referenced by html :
<script type='text/javascript' src="js/settings.js"></script>
I would like to define the solr path in application.yml at runtime as follows:
app:
solr:
path: 'http://solr:8983/solr/operations/select/'
Question
What is the best way to "populate" this settings.js value from application.properties (or equivalent, i.e. command line arguments, e.g.:
-Dapp.solr.path=...
)
Possible
I thought about putting 'settings.js' as a thymeleaf template (settings.js.html) and having a spring controller populate the model from application.properties.
I didn't know if a more "native spring" method existed.
Thanks!
You could use a ResourceTransformer:
#Component
public class InjectSolrPathResourceTransformer implements ResourceTransformer {
private final MySetting settings; // inject via constructor
#Override
public Resource transform(HttpServletRequest request, Resource resource, ResourceTransformerChain transformerChain) throws IOException {
if (request.getServletPath().equals("/js/settings.js")) {
byte[] bytes = FileCopyUtils.copyToByteArray(resource.getInputStream());
String content = new String(bytes, StandardCharsets.UTF_8);
content = content.replace("var SERVERROOT = SERVERROOT_VALUE",
"var SERVERROOT = '" + settings.getSolrPath() + "'");
return new TransformedResource(resource, content.getBytes(StandardCharsets.UTF_8));
} else {
return resource;
}
}
}
This assumes that you change settings.js to be:
var SERVERROOT = SERVERROOT_VALUE
To use the ResourceTransformer, register it in your WebMvcConfigurer:
#Configuration
public class WebConfig implements WebMvcConfigurer {
// inject this via constructor
private final InjectSolrPathResourceTransformer resourceTransformer;
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/js/**")
.addResourceLocations("classpath:/public/js/")
.addTransformer(resourceTransformer);
}
}
The answer of #Wim above is correct but with new spring boot edition use the below code to register your transformer;
#Configuration
public class WebConfig implements WebMvcConfigurer {
// inject this via constructor
private final InjectSolrPathResourceTransformer resourceTransformer;
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/js/**")
.addResourceLocations("classpath:/public/js/")
.resourceChain(false)
.addTransformer(resourceTransformer);
}
}

How to define global static header on Spring Boot Feign Client

I have a spring boot app and want to create a Feign client which has a statically defined header value (for auth, but not basic auth). I found the #Headers annotation but it doesn't seem to work in the realm of Spring Boot. My suspicion is this has something to do with it using the SpringMvcContract.
Here's the code I want to work:
#FeignClient(name = "foo", url = "http://localhost:4444/feign")
#Headers({"myHeader:value"})
public interface LocalhostClient {
But it does not add the headers.
I made a clean spring boot app with my attempts and posted to github here: github example
The only way I was able to make it work was to define the RequestInterceptor as a global bean, but I don't want to do that because it would impact other clients.
You can also achieve this by adding header to individual methods as follows:
#RequestMapping(method = RequestMethod.GET, path = "/resource", headers = {"myHeader=value"})
Using #Headers with dynamic values in Feign client + Spring Cloud (Brixton RC2) discusses a solution for dynamic values using #RequestHeader.
You can set a specific configuration class on your feign interface and define a RequestInterceptor bean in there. For example:
#FeignClient(name = "foo", url = "http://localhost:4444/feign",
configuration = FeignConfiguration.class)
public interface LocalhostClient {
}
#Configuration
public class FeignConfiguration {
#Bean
public RequestInterceptor requestTokenBearerInterceptor() {
return new RequestInterceptor() {
#Override
public void apply(RequestTemplate requestTemplate) {
// Do what you want to do
}
};
}
}
You could specify that through the application.yml file:
feign:
client:
config:
default:
defaultRequestHeaders:
Authorization:
- Basic 3ncond2dS3cr2t
otherHeader:
- value
Note that this will be applicable to all your Feign Clients if it happened that you're using more than one. If that's the case, you could add a section per client instead of adding this to the default section.
Try this
#Component
public class AuthFeignInterceptor implements RequestInterceptor {
#Override
public void apply(RequestTemplate template) {
final RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
if (requestAttributes != null) {
final HttpServletRequest httpServletRequest = ((ServletRequestAttributes) requestAttributes).getRequest();
template.header("Header_name","Value");
}
}
}

Spring Annotation-Based Interceptor

can any of you please post a snippet for the following. I've looked in a couple of places but they all seem to be xml based. I'd like to have this code in java configuration style only.
I am trying to accomplish the following..
1) I need to intercept a specific url, for example "http://localhost:8080/test" and only a url that starts with "/test/*". This is not a spring security question, this is just for an endpoint I like to intercept.
2) I need to intercept the HttpServletRequest object of that request and add a specific header to that request. For example, "authorization", "bearer xxxx".
3) When the /test endpoint finally hits, I should be able to see the authorization header inside my HttpServletRequest object.
Thank you guys.
you can do this like this:
(Whithin "YourOwnInterceptor" you can add the value to the header...)
#Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
#Bean
public YourOwnInterceptor yourOwnInterceptor() {
return new YourOwnInterceptor();
}
#Override
public void addInterceptors(InterceptorRegistry registry) {
super.addInterceptors(registry);
registry.addInterceptor(yourOwnInterceptor()).
addPathPatterns("/<your-url-to-intercept>/**");
}
}

Add interceptor to spring boot mongodb rest example

I am trying to add an interceptor to a simple Spring-boot-mongodb-rest app, as can be seen here : http://spring.io/guides/gs/accessing-mongodb-data-rest/, in order to perform certain actions after the default rest handler is invoked. Here is my MongoRepository, whose CRUD operation is called upon a POST request to the server:
#RepositoryRestResource(collectionResourceRel = "reminder", path = "reminder")
public interface ReminderRepository extends MongoRepository<Reminder, String> {
List<Reminder> findBySendee(#Param("sendee") String sendee);
}
I am trying to register an interceptor for all HTTP requests by extending the WebMvcConfigurerAdapter class like this:
#Configuration
#ComponentScan
public class RemindxWebConfig extends WebMvcConfigurerAdapter {
#Override
public void addInterceptors(InterceptorRegistry registry){
registry.addInterceptor(new RemindxInterceptor());
}
}
As mentioned in the spring boot docs, I have not added the #EnableWebMvc annotation to this. While running the application, the addInterceptors function does get called and adds the interceptor. However, the given interceptor is not called after the POST handler is invoked. I am unable to figure out a way to have spring use this RemindxWebConfig for all MongoRepository http requests. Any inputs are appreciated.

Resources