override spring-boot property in dependency jar file - spring

I have a spring boot project that depends on one of the 3rd party SDK libraries which contains a YAML file with some google cloud URLs.
I want to override those values within my YAML, this works for most of my project but for some reason no luck with this perticular dependency lib.
The Dependency Code
#ConfigurationProperties("google")
public class GoogleProperties {
String url;
..
..
}
Yaml file application-google-prod.yaml
google:
url: some url.
Say this is in a jar called google-client-sdk-1.0.0
My Code
Yaml file application-myapp-prod.yaml
spring:
profiles:
include: google-prod
google:
url: OVERRIDE url.
So I am expecting that the OVERRIDE url should be used when the code in the lib is invoked, but instead it continues to use some url from jar file's yaml.
any pointers?
EDIT
The SDK contains another class
class with the following annotations in the SDK
#Configuation
#PropertySource({"classpath:application-google-prod.yaml})
I think this is forcing SDK to pick the value from the specific YAML ignoring overridden value in the YAML from my app.

Disclaimer:
A is have no mean reproducing your issue, this is just a suggestion.
Notice the absence of #Configuration on GoogleProperties.
You have to either add #Configuration on the properties class:
(impossible in this case) or add #EnableConfigurationProperties(GoogleProperties.class) on top of the class where you want to use the properties.
E.g: Your main class if you want to use them in all the app.
As mentioned in the docs, you can also use:
#ConfigurationPropertiesScan({ "com.google.SDK", "org.acme.another" }) on top of your main class or any #Configuration class where you need those props.
Note: As explained here, the fact that as of spring-boot 2.2 we didn't need any more #Configuration or #EnableConfigurationProperties for the configuration properties feature is outdated.

Related

Swagger not generating paths in yaml/json file when code is compiled

Trying to generate API documentation for a spring boot application using swagger. Using swagger-maven-plugin to generate yaml documentation from code. After compiling, the generated yaml/json file does not contain any path. However the controller class where the APIs are defined is getting scanned. But none of the APIs defined there are showing up in documentation. However accessing http://localhost:8080/api-docs shows a json and that is listing all the APIs as expected. What could be the issue? I have made sure of the following:
controller is annotated with #Api
tag value is set to false in pom.xml
basepath is the same across pom and controller class
All API paths are of the form http://localhost:8080/{id}/
Got my problem resolved. The Controller class methods were not declared public and hence was not showing up in swagger.yaml and json files even though the api-docs were listing them.
Try mapping your controller into a path.
Eg:- #Controller #RequestMapping(value = "/api")
For further clarification you can refer this article: https://www.baeldung.com/spring-controllers

spring boot app cannot load bundle properties files

I am building an app that mostly provide REST services, nothing fancy. since my data consumed by the app can have multiple languages I thought about using the bundle files.
I created 3 files, one with the default file name and another two with specific languages. The files created using intellij IDE I am using.
I followed this guide https://www.baeldung.com/java-resourcebundle however on each run I am getting:
MissingResourceException: Can't find bundle for base name tp_app_strings, locale en_US
I tried numerous articles but none of them seems to resolve the issue.
One fun fact is that if I am using the #Value("classpath:tp_app_strings.properties") on a 'Resource' field I am able to get a reference to that file, so it spring is able to find it.
Additional thing that I tried was to create a WEB-INF directory and place the files there (read it in some article) but still no positive affect
The project structure is quite straight forward:
Spring boot version 2.2 running tomcat.
Any suggeestions would be highly appriciated
You can load the .properties file to the application context using #PropertySource annotation instead using #Value to load the .properties file to a org.springframework.core.io.Resource instance.
The usage;
#Configuration
#PropertySource("classpath:tp_app_strings.properties")
public class DefaultProperties {
#Value("${property1.name}") // Access properties in the above file here using SpringEL.
private String prop1;
#Value("${property2.name}")
private String prop2;
}
You wouldn't need java.util.ResourceBundle access properties this way. Use different or same class to load other .properties files as well.
Update 1:
In order to have the functionality of java.util.ResourceBundle, you can't just use org.springframework.core.io.Resource class. This class or non of it sub-classes don't provide functions to access properties by its name java.util.ResourceBundle whatsoever.
However, if you want a functionality like java.util.ResourceBundle, you could implement something custom like this using org.springframework.core.io.Resource;
#Configuration
public class PropertyConfig {
#Value("classpath:tp_app_strings.properties")
private Resource defaultProperties;
#Bean("default-lang")
public java.util.Properties getDefaultProperties() throws IOException {
Properties props = new Properties();
props.load(defaultProperties.getInputStream());
return props;
}
}
Make sure to follow correct naming convention when define the property file as java.util.Properties#load(InputStream) expect that.
Now you can #Autowire and use this java.util.Properties bean wherever you want just like with java.util.ResourceBundle using java.util.Properties#getProperty(String) or its overloaded counterpart.
I think it's problem of you properties file naming convention. use underline "_" for specifying locale of file like
filename_[languageCode]_[regionCode]
[languageCode] and [regionCode] are two letters standard code that [regionCode] section is optional
about code abbrivation standard take a look on this question
in your case change file name to tp_app_strings_en_US.properties

How can I set the base path for my RESTEasy resources in Quarkus?

I would like to set the base path under which all my RESTEasy resources would fall, without having to include a class that extends javax.ws.rs.core.Application.
Basically I would like to get rid of:
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
#ApplicationPath("/api")
public class MyApplication extends Application {
}
How can I achieve that?
Quarkus allows the base path to be configured in application.properties (see here).
So simply replace the class above with the following in application.properties:
quarkus.resteasy.path=/api
UPDATE
When using RESTEasy Reactive, as pointed out by https://stackoverflow.com/a/72426133/2504224, one needs to use:
quarkus.resteasy-reactive.path=/api/
The accepted answer works for quarkus resteasy classic.
If you are using quarkus-resteasy-reactive you will need to set:
quarkus.resteasy-reactive.path=/api/
I am using Quarkus 2.13.1 and I made the following configuration. More info.
Modify application.properties file and add the following lines
# Apply this path for the whole application, including metrics, etc.
quarkus.http.root-path=/api/
# In case you want to change a different route
quarkus.http.non-application-root-path=/q

Exclude some components of a Microservice

I am a new bee and using microservices(Spring Boot, Spring Cloud) in which I am trying to use resource file of a microservice in another. For that I need to scan that module in another one via ComponentScan.
Like I have an Admin module in which I need to autowired Main Resource that is in main module.So I use:
#ComponentScan(basePackages = {"com.example.admin","com.example.main"}
I used this in AdminApplication file.Now it also shows Main module's Controllers in Admin which I don't want. I google it and apply:
#ComponentScan(basePackages =
{"com.example.admin","com.example.main"},
excludeFilters = {#ComponentScan.Filter(type = ASSIGNABLE_TYPE,
value = {
UserController.class,
CustomerController.class,
SchoolController.class
})})
But it still shows this Main module controllers in Admin Module. How to actually exclude this? Please help me.
With JavaConfig (#Configuration) and the #Profile annotation, you could set up a subtile combination of classes "in and out" depending of your needs, I guess.
BUT you would have to disable #ComponentScan on your main class (don't use #SpringBootApplication, maybe, as it's embedding #ComponentScan).
IMHO you should rather modularize your applications/services, building common resources as a separated JAR, and each service as a distinct Maven module depending on it
Thanks for your suggestions. Finally I got the answer.
Swashbuckle is built on top of WebApi's built-in metadata layer - ApiExplorer. If you decorate a controller or action with the following attribute:
[ApiExplorerSettings(IgnoreApi=true)]
public class MyController : ApiController
then this will ultimately cause the entire controller or individual action to be omitted from the Swagger output .

Spring Boot profile specific properties

I'm using Sprint Boot, and would like to have multiple profile specific property files. The docs state:
In addition to application.properties files, profile specific
properties can also be defined using the naming convention
application-{profile}.properties.
http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-external-config-profile-specific-properties
However I have multiple properties files (e.g. db.properties). I'm loading currently load this non-profile specific file as:
#Configuration
#PropertySource( {"classpath:db.properties"} )
class DataSourceConfig {
#Value("db.server") String server;
...
}
How can I combine these two things together, so it loads db-dev.properties like Spring Boot does for application.properties
It sounds like it should be easy, but I can't work out how to do it?!
Java -jar my-spring-boot.jar --spring.profiles.active=test you can set profile.active=your environment via commandline
I just saw that you use #PropertySource. The docs say:
Profile specific variants of both application.properties (or application.yml) and files referenced via #ConfigurationProperties are considered as files are loaded.

Resources