How to resolve placeholder value in SpringBoot - java

Kindly help with accessing values from yaml file in Sprint Boot. I am getting error as below. I am able to access value of filepath1 variable in AppConfig class but not sure why its giving the error.
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'filepath1' in value "${filepath1}"
at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:178)
at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:124)
at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:239)
at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:210)
My main class is as follows
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args)
{
System.out.println("Starting ");
SpringApplication.run(DemoApplication.class, args);
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(DemoApplication.class);
Employee employee = applicationContext.getBean(Employee.class);
System.out.println("Exiting ");
}
}
Config class is as follows
#Slf4j
#Configuration
#ComponentScan("com.vish.springbootdemo.demo")
public class AppConfig
{
#Value("${filepath1}")
private String file1;
#Bean
public Employee employee()
{
System.out.println("file1 is " + file1);
return new Employee();
}
}
Here is the application.yml
filepath1: "vish"

The problem is that in the main method, you are creating your own application context:
ApplicationContext applicationContext =
new AnnotationConfigApplicationContext(DemoApplication.class);
This will be completely separate from the application context that Spring Boot creates for you, and won't have the configuration properties from application.yml in it.
Instead of doing this, use the application context that Spring Boot provides. Even better: Don't explicitly lookup a bean in the application context, but let Spring Boot autowire the bean for you.
Something like this:
#SpringBootApplication
public class DemoApplication implements CommandLineRunner {
#Autowired
private Employee employee;
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
#Override
public void run(String... args) throws Exception {
System.out.println("Employee: " + employee);
}
}
AppConfig:
#Configuration
public class AppConfig {
#Value("${filepath1}")
private String file1;
#Bean
public Employee employee() {
System.out.println("file1 is " + file1);
return new Employee();
}
}

Start your spring boot application like this:
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
Resources folder should contain application.yml.
filepath1: vish
Inject your bean with #Autowired
#Component
class AnotherComponent {
#Autowired Employee employee;
}

Related

Failed to set value with application.properties

I'm trying a very simple code to inject a value from application.properties.
The value which is setted is the property name.
What's wrong with the code?
application.properties
set.browser = ie
public class A {
#Value("${set.browser}")
private String browser;
public A(){}
public void print(){
System.out.println(browser);
}
}
#Configuration
public class ABean {
#Bean
public A getA(){
return new A();
}
}
public class AMain {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(A.class);
A a = context.getBean(A.class);
a.print();
}
}
First of all your application is not spring boot application - you've just instanted spring context even without component scan. Secondly beacause of lack of component scan, your ABean is never created - your context has only A bean. To fix this you can create context from ABean:
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ABean.class);
Thirdly you didn't configured PropertySource (if your application was spring boot application, application.properties would be default property source and it wouldn't be needed):
#PropertySource("classpath:/application.properties")
#Configuration
class ABean {
#Bean
public A getA() {
return new A();
}
}

Unable to Autowire

Using Spring Initializer to create a simple Spring boot. I am only choosing DevTools under the options available.
After creating the project, without making any changes to it, able to run the program fine.
Now when I try to do some Autowiring in the project, it simply doesn't work. I don't get it. Been looking all over previous questions here which has resolutions for it but none works plus there is nothing complex about what I am doing in my case as follows. Please advice what I am missing.
#SpringBootApplication
public class DemoApplication {
// #Autowired
// private static Maker maker; // Stopped using this cos I wanted to check if the autowiring is not working in this class only or anywhere. Turns out it is anywhere.
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
Maker maker = new Maker();
maker.printName(); // Fails cos of ServiceHelper Autowiring
}
}
#Service
public class Maker {
#Autowired
private ServiceHelper serviceHelper;
public void printName(){
System.out.println("This is from the method body itself.");
System.out.println("Auto wiring works cos I got this -> " + serviceHelper.help());
}
}
#Component
public class ServiceHelper {
public String help(){
return "...FROM HELPER...";
}
}
StackTrace
Exception in thread "restartedMain"
java.lang.reflect.InvocationTargetException at
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497) at
org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Caused by: java.lang.NullPointerException at
com.example.demo.services.Maker.printName(Maker.java:15) at
com.example.demo.DemoApplication.main(DemoApplication.java:17) ... 5
more
If you create any bean using new keyword that bean will not added to Spring Application Context, and this is one way to #Autowire static beans
#SpringBootApplication
public class DemoApplication {
#Autowired
private static Maker maker;
#Autowired
private Maker tMaker;
#PostConstruct
public void init() {
DemoApplication.maker = tMaker;
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
maker.printName();
}
}
or you can do Autowire using Constructor the instance of Maker is injected as an argument to the constructor when DemoApplication is created
#Autowired
public DemoApplication(Maker maker) {
DemoApplication.maker = maker;
}
or you can use #Autowired on setter method, the setter method is called with the instance of Maker when DemoApplication is created
#Autowired
public void setMaker(Maker maker) {
DemoApplication.maker = maker
}
You create yourself an instance, its ServiceHelper does not get autowired by Spring:
Maker maker = new Maker();
You can access bean via ApplicationContext:
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
ApplicationContext cts = SpringApplication.run(DemoApplication.class, args);
Maker maker = ctx.getBean(Maker.class);
maker.printName();
}
}
When you use new Maker() you are not using the bean Spring created for you and as a result the the object you have is uninitialized as dependencies are not injected.
You need to get the bean which the Spring framework created, like I did below as directly you cannot autowire static fields:
#SpringBootApplication
public class DemoApplication {
private static Maker maker;
#Autowired
public void setMaker(Maker maker) {
DemoApplication.maker = maker;
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
maker.printName();
}
}

Initializa Bean with YAML configuration in Spring Boot

I would like to read some properties, like DB access configs, when initializing bean or service in spring boot.
Anyone knows good ways ?
This is my current code snippet.
public class SampleApplication implements ApplicationRunner
{
#Autowired
private YAMLConfig myConfig;
#Override
public void run(ApplicationArguments args) throws Exception
{
System.out.println(myConfig != null); //YAMLConfig has been intialized here
}
public SampleApplication()
{
System.out.println(myConfig == null); //myConfig is null
}
#Configuration
public static class Config
{
#Bean
#ConditionalOnProperty(value = {"batch.execute"}, havingValue = "SampleApplication")
public SampleApplication sampleApplication()
{
return new SampleApplication();
}
}
}
#Configuration
#EnableConfigurationProperties
#ConfigurationProperties
public class YAMLConfig
{
private String environment;
public String getEnvironment()
{
return environment;
}
public void setEnvironment(String environment)
{
this.environment = environment;
}
}
Thanks for taking a look at this!
create this method inside your SampleApplication class
#PostConstruct
public void init() {
// at this point, all the dependency injection has happened already
myConfig.doStuff()
}
it will be called by spring automatically after all bean initialization has been done.

How to proper create bean Spring using annotations Bean and ComponentScan?

Main:
#SpringBootApplication
#ComponentScan(basePackageClasses = Application.class)
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Test class:
public class Test {
#Bean
public Test test(){
return new Test();
}
}
and when I'm trying to autowire it then i got this exception:
***************************
APPLICATION FAILED TO START
***************************
Description:
Field test in TestWithAutowire required a bean of type 'Test' that could not be found.
Action:
Consider defining a bean of type 'rcms.backend.exception.Test' in your configuration.
Process finished with exit code 1
There is something hat I'm doing wrong, but I can't find it out.
You can create a new configuration, let's say SpringConfiguration,
package my.pkg.config;
#Configuration
public class SpringConfiguration {
#Bean
public Test test(){
return new Test();
}
}
In your Application class, you can add the #ComponentScan annotation with the base packages where you would like Spring to scan for classes,
#SpringBootApplication
#ComponentScan(basePackageClasses = {"my.pkg.config", "my.pkg.example"})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Now you can autowire Test in any Spring component. For example,
package my.pkg.example;
#Component
public class TestExample {
#Autowired
private Test tst;
}

#Autowired fails in spring boot web project

I have a simple Spring Boot web project, right from a template:
#SpringBootApplication
#RestController
public class HelloWorldRestApplication {
public static void main(String[] args) {
SpringApplication.run(HelloWorldRestApplication.class, args);
Performer p = new Performer();
p.perform();
}
}
I have a test to ensure autowiring works, and in fact it does in this test class (examples come from Spring in Action, 4th):
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes=CDPlayerConfig.class)
public class CDPlayerTest {
#Autowired
private CDPlayer cdp;
#Test
public void cdShouldNotBeNull(){
assertNotNull(cdp);
}
}
and:
public class Performer {
#Autowired
private CDPlayer cdp;
public void perform(){
System.out.println(cdp);
cdp.play();
}
public CDPlayer getCdp() {
return cdp;
}
public void setCdp(CDPlayer cdp) {
this.cdp = cdp;
}
}
and:
#Component
public class CDPlayer{
public void play(){
System.out.println("play");
}
}
config:
#Configuration
#ComponentScan
public class CDPlayerConfig {
}
However, it doesnt work in HelloWorldRestApplication, I get null.
Adding #ContextConfiguration(classes=CDPlayerConfig.class) doesn't help.
What do I miss?
Try enabling #ComponentScan your packages in your main class and get Performer class instance from ApplicationContext as below:
#SpringBootApplication
#RestController
#ComponentScan({“package.name.1”,”package.name.2”})
public class HelloWorldRestApplication {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(HelloWorldRestApplication.class, args);
Performer p = ctx.getBean(Performer.class);//get the bean by type
p.perform();
}
}

Categories

Resources