I have a person model class that needs to be immutable and singleton. I need to autowire from my service class but getting an error.
So is there any way to create a singleton immutable class in spring boot? where i can set values in person (via autowire) and use the same in the entire application.
I have just started learning spring-boot. I searched on google and found the solution with Lombok but somehow it didn’t work for me.
My person model :
@Value @Builder @AllArgsConstructor(access = AccessLevel.PRIVATE) @Component public final class Person { private final String firstName; private final String lastName; } //My service class @Component public class ArgumentReadingService { @Autowired Person person; public void readArguments() { person = Person.builder().firstName("Hello").build(); System.out.println("name : "+person.getFirstName()); }
Error :
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled. 2021-03-10 17:52:29.197 ERROR 8824 --- [ main] o.s.boot.SpringApplication : Application run failed org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'person' defined in file [C:UsersUserDesktopWorkSpaceOrion.Strat1.bidAsk_StptargetclassesorionmodelPerson.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [orion.model.Person]: No default constructor found; nested exception is java.lang.NoSuchMethodException: orion.model.Person.<init>() at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1316) ~[spring-beans-5.3.4.jar:5.3.4] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1214) ~[spring-beans-5.3.4.jar:5.3.4] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:564) ~[spring-beans-5.3.4.jar:5.3.4] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524) ~[spring-beans-5.3.4.jar:5.3.4] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.4.jar:5.3.4] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.4.jar:5.3.4] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.4.jar:5.3.4] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.4.jar:5.3.4] at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944) ~[spring-beans-5.3.4.jar:5.3.4] at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:917) ~[spring-context-5.3.4.jar:5.3.4] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:582) ~[spring-context-5.3.4.jar:5.3.4] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:767) [spring-boot-2.4.3.jar:2.4.3] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759) [spring-boot-2.4.3.jar:2.4.3] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:426) [spring-boot-2.4.3.jar:2.4.3] at org.springframework.boot.SpringApplication.run(SpringApplication.java:326) [spring-boot-2.4.3.jar:2.4.3] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1311) [spring-boot-2.4.3.jar:2.4.3] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1300) [spring-boot-2.4.3.jar:2.4.3] at com.orion.Application.main(Application.java:20) [classes/:na] Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [orion.model.Person]: No default constructor found; nested exception is java.lang.NoSuchMethodException: orion.model.Person.<init>() at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:83) ~[spring-beans-5.3.4.jar:5.3.4] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1308) ~[spring-beans-5.3.4.jar:5.3.4] ... 17 common frames omitted Caused by: java.lang.NoSuchMethodException: orion.model.Person.<init>() at java.lang.Class.getConstructor0(Class.java:3082) ~[na:1.8.0_191] at java.lang.Class.getDeclaredConstructor(Class.java:2178) ~[na:1.8.0_191] at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:78) ~[spring-beans-5.3.4.jar:5.3.4] ... 18 common frames omitted
Advertisement
Answer
This configuration class and that annotation will provide you always with that Person Bean
@Configuration public class ServerConfig { @Bean private Person getPerson(){ return new Person("name", "lastName"); }
Now it will be available everywhere for autowiring.
As the comments note however, it seems strange to use a model class as a Singleton.