Spring boot application with EnableCaching How to retrieve guava cache content - spring

It'm using a spring boot application with cache enabled.
Environment (pom.xml):
Spring:
org.springframework.boot:spring-boot-starter-amqp:jar:1.3.3.RELEASE
org.springframework:spring-messaging:jar:4.2.5.RELEASE
org.springframework.amqp:spring-rabbit:jar:1.5.4.RELEASE
org.springframework.retry:spring-retry:jar:1.1.2.RELEASE
org.springframework:spring-core:jar:4.2.5.RELEASE:compile
org.springframework.cloud:spring-cloud-aws-context:jar:1.0.4.RELEASE
org.springframework:spring-context:jar:4.2.5.RELEASE
org.springframework.data:spring-data-jpa:jar:1.9.4.RELEASE
org.springframework:spring-context-support:jar:4.2.5.RELEASE
Hibernate
org.hibernate:hibernate-validator:jar:5.2.2.Final
org.hibernate.javax.persistence:hibernate-jpa-2.1-api:jar:1.0.0.Final
com.fasterxml.jackson.datatype:jackson-datatype-hibernate4:jar:2.6.5
org.hibernate:hibernate-entitymanager:jar:5.1.0.Final
org.hibernate.common:hibernate-commons-annotations:jar:5.0.1.Final
org.hibernate:hibernate-java8:jar:5.1.0.Final
org.hibernate:hibernate-envers:jar:5.1.0.Final
Configuration Cache (on Spring boot application):
#Configuration
#EnableCaching
public class ApplicationCacheConfig extends CachingConfigurerSupport {
/**
* Configuration Table Cache
*/
public static final String CONFIGURATION_TABLE_FIND_BY_ID_CACHE_NAME = "CONFIGURATION_TABLE_FIND_BY_ID_CACHE";
public static final String CONFIGURATION_TABLE_FIND_SERVICE_ID_CACHE_NAME = "CONFIGURATION_TABLE_FIND_SERVICE_ID_CACHE";
#Bean
#Override
public CacheManager cacheManager() {
SimpleCacheManager simpleCacheManager = new SimpleCacheManager();
Collection<Cache> caches = Lists.newArrayList();
caches.addAll(buildConfigurationCache());
simpleCacheManager.setCaches(caches);
return simpleCacheManager;
}
private Collection<Cache> buildConfigurationCache() {
List<Cache> caches = Lists.newArrayList();
// This cache never expires and don't have a maximum size because the table Configuration is not transactional
GuavaCache cacheFindById = new GuavaCache(CONFIGURATION_TABLE_FIND_BY_ID_CACHE_NAME,
CacheBuilder.newBuilder().build());
caches.add(cacheFindById);
// This cache never expires and don't have a maximum size because the table Configuration is not transactional
GuavaCache cacheFindByService = new GuavaCache(CONFIGURATION_TABLE_FIND_SERVICE_ID_CACHE_NAME,
CacheBuilder.newBuilder().build());
caches.add(cacheFindByService);
return caches;
}
}
Hibernate entity:
#Entity
#Table(name = Configuration.TABLE_NAME)
#DynamicUpdate
public class Configuration implements Serializable {
public static final String TABLE_NAME = "configuration";
private static final long serialVersionUID = 1L;
#Id
#Column(name = "id")
#Convert(converter = ConfigurationConverter.class)
private ConfigurationEnum id;
#Column(name = "service", nullable = false)
#NotNull
#Convert(converter = ServiceConverter.class)
private ServiceEnum service;
}
Repository (Spring-data):
public interface ConfigurationRepository extends PagingAndSortingRepository<Configuration, Integer>,
JpaSpecificationExecutor<Configuration> {
#Cacheable(ApplicationCacheConfig.CONFIGURATION_TABLE_FIND_BY_ID_CACHE_NAME)
Configuration findById(ConfigurationEnum configurationEnum);
#Cacheable(ApplicationCacheConfig.CONFIGURATION_TABLE_FIND_SERVICE_ID_CACHE_NAME)
List<Configuration> findByService(ServiceEnum service);
}
Configuration Enum:
#Getter
#AllArgsConstructor
public enum ConfigurationEnum {
CONFIG_1(1),
CONFIG_2(2);
private int id;
}
Configuration Converter:
#Converter
public class ConfigurationConverter implements AttributeConverter<ConfigurationEnum, Integer> {
#Override
public Integer convertToDatabaseColumn(ConfigurationEnum key) {
return key == null ? null : (int) key.getId();
}
#Override
public ConfigurationEnum convertToEntityAttribute(Integer key) {
return key == null ? null : Stream.of(ConfigurationEnum.values())
.filter(step -> key.equals(step.getId()))
.findFirst()
.orElse(null);
}
}
Test IT:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = ApplicationIT.class)
#WebAppConfiguration
#Transactional
public class ConfigurationCacheIT {
#Autowired
ConfigurationRepository configurationRepository;
#Autowired
protected CacheManager cacheManager;
#Test
public void configuration_findById_cache_success() {
Configuration config = configurationRepository.findById(ConfigurationEnum.CONFIG_1);
// An ORM request is performed - CHECK
Assert.assertNotNull(step); // TEST OK
Cache.ValueWrapper entry = getCacheEntry(ApplicationCacheConfig.CONFIGURATION_TABLE_FIND_BY_ID_CACHE_NAME, ConfigurationEnum.CONFIG_1.getId());
Assert.assertNull(entry); OK
config = configurationRepository.findById(ConfigurationEnum.CONFIG_1);
// No ORM request is performed - CHECK
Assert.assertNotNull(step); // TEST OK
entry = getCacheEntry(ApplicationCacheConfig.CONFIGURATION_TABLE_FIND_BY_ID_CACHE_NAME, ConfigurationEnum.CONFIG_1.getId());
Assert.assertNotNull(entry); **// TEST FAIL !!!**
entry = getCacheEntry(ApplicationCacheConfig.CONFIGURATION_TABLE_FIND_BY_ID_CACHE_NAME, ConfigurationEnum.CONFIG_1.name());
Assert.assertNotNull(entry); **// TEST FAIL !!!**
entry = getCacheEntry(ApplicationCacheConfig.CONFIGURATION_TABLE_FIND_BY_ID_CACHE_NAME, ConfigurationEnum.CONFIG_1);
Assert.assertNotNull(entry); **// TEST FAIL !!!**
}
protected Cache.ValueWrapper getCacheEntry(String cacheName, Object key) {
return cacheManager.getCache(cacheName).get(key);
}
#Test
public void configuration_findByAll_without_cache_success() {
ArrayList<Configuration> list1 = Lists.newArrayList(configurationRepository.findAll());
// An ORM request is executed
Assert.assertNotNull(list1);
Assert.assertEquals(ConfigurationEnum.values().length, list1.size());
ArrayList<Configuration> list2 = Lists.newArrayList(configurationRepository.findAll());
// Another ORM request is executed
Assert.assertNotNull(list2);
Assert.assertEquals(ConfigurationEnum.values().length, list2.size());
}
}
My question is why my tests are failing?

Actually this was a non issue.
I'm using the fallowing architecture:
App-mdw (Middleware layer) (Spring boot App with #EnableCaching annotation)
App-ws (WebServices layer) (Spring boot App without #EnableCaching annotation)
The above tests were executed on the application App-ws and the annotation is not inherited that's why the caching was not working.
The right assert was:
entry = getCacheEntry(ApplicationCacheConfig.CONFIGURATION_TABLE_FIND_BY_ID_CACHE_NAME, ConfigurationEnum.CONFIG_1);
Assert.assertNotNull(entry)

Related

Entity listener can inject other Spring dependencies but not repository

I have this entity listener class:
#Component
public class AssignmentListener {
private KafkaService kafkaService;
private String topic;
private AssignmentMapper assignmentMapper;
private AttachmentRepository attachmentRepository;
#Autowired
public final void setKafkaService(KafkaService kafkaService) {
this.kafkaService = kafkaService;
}
#Autowired
public final void setTopic(
#Value("${topic}") String topic
) {
this.topic = topic;
}
#Autowired
public final void setAssignmentMapper(AssignmentMapper assignmentMapper) {
this.assignmentMapper = assignmentMapper;
}
#Autowired
public final void setAttachmentRepository(AttachmentRepository attachmentRepository) {
this.attachmentRepository = attachmentRepository;
}
#PostPersist
#PostUpdate
#Transactional("transactionManager")
#TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT)
public void postUpdate(Assignment assignment) {
var attachments = attachmentRepository.findAllByAssignmentId(assignment.getId());
var dto = assignmentMapper.mapToKafkaMessage(assignment);
dto.setAttachments(
attachments.stream()
.map(Attachment::getPath)
.collect(Collectors.toSet())
);
kafkaService.sendMessage(
topic,
dto
);
}
}
and it worked normally until adding this last field which is repository. All other dependencies were injected however no matter what I do this won't get injected. Just to mention this is happening in tests. Do you have any suggestion?

Hibernate does not create proxy within #DataJpaTest

I have a very simple test that tests the spring data repository that works ok in normal runtime. I really don't think it should be this difficult to do this, but I do not understand what I am doing wrong, please help.
When I try to test this repository I start receiving errors that say something like:
Caused by: org.hibernate.HibernateException: Generation of
HibernateProxy instances at runtime is not allowed when the configured
BytecodeProvider is 'none'; your model requires a more advanced
BytecodeProvider to be enabled. at
org.hibernate.bytecode.internal.none.DisallowedProxyFactory.getProxy(DisallowedProxyFactory.java:37)
at
org.hibernate.tuple.entity.AbstractEntityTuplizer.createProxy(AbstractEntityTuplizer.java:746)
at
org.hibernate.persister.entity.AbstractEntityPersister.createProxy(AbstractEntityPersister.java:5049)
It appears that hibernate can not create a proxy for entity classes, because it for some reason has been assigned a DisallowedProxyFactory implementation for proxy factory. So I added this configs:
spring.jpa.properties.hibernate.enhancer.enableDirtyTracking=true
spring.jpa.properties.hibernate.enhancer.enableLazyInitialization=true
But now I simply receive this error instead:
Caused by: java.lang.IllegalStateException: Cannot apply class
transformer without LoadTimeWeaver specified at
org.springframework.orm.jpa.persistenceunit.SpringPersistenceUnitInfo.addTransformer(SpringPersistenceUnitInfo.java:83)
So I added #EnableLoadTimeWeaving to the test class, and now I receive this error
Caused by: java.lang.IllegalStateException: ClassLoader
[jdk.internal.loader.ClassLoaders$AppClassLoader] does NOT provide an
'addTransformer(ClassFileTransformer)' method. Specify a custom
LoadTimeWeaver or start your Java virtual machine with Spring's agent:
-javaagent:spring-instrument-{version}.jar
The initial test set up:
#DataJpaTest
#Transactional
#Import({RdsPersistenceConfigration.class})
class DivisionRepositoryTest {
#Autowired
private DivisionRepository repository;
#Test
#Sql(scripts = "classpath:sql/division-repository-test.sql")
void crudOperations() {
// test case logic
}
}
Division entity:
#Entity
#Getter
#Setter
#NoArgsConstructor
#Table(name = "division")
public class Division {
private transient static final int HASH_CODE = Division.class.hashCode();
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Column(name = "division_name", nullable = false)
private String divisionName;
#OneToMany(mappedBy = "division", fetch = FetchType.LAZY)
private Set<Branch> branches = new HashSet<>();
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "tenant_id", nullable = false)
private Tenant tenant;
public void setTenant(Tenant tenant) {
if (tenant != null) {
this.tenant = tenant;
tenant.addDivision(this);
} else {
if (this.tenant != null) this.tenant.removeDivision(this);
this.tenant = tenant;
}
}
#Transient
public void addBranch(Branch branch) {
if (branch != null) {
if (branch.getDivision() != this) {
branch.getDivision().removeBranch(branch);
}
branches.add(branch);
}
}
#Transient
public void removeBranch(Branch branch) {
if (branch != null) {
branches.remove(branch);
}
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Division division = (Division) o;
return Objects.equals(id, division.id);
}
#Override
public int hashCode() {
return Division.HASH_CODE;
}
}
Repository:
public interface DivisionRepository extends JpaRepository<Division, Integer> {
Page<Division> findAll(Pageable pageable);
}
Rds Persistence config class
#Configuration
#PropertySource("classpath:application-liquibase.properties")
#EntityScan("com.nflp.processingapplication.main.modules.persistence.sql")
public class RdsPersistenceConfigration {
}
Updated test after suggestion from #M. Denium
#DataJpaTest
#Transactional
#TestPropertySource(properties = "spring.liquibase.change-log=classpath:db/changelog/changelog.master.xml")
class DivisionRepositoryTest {
#Autowired
private DivisionRepository repository;
Ok, I finally found the solution, the reason was in something I did not even suspect, my application uses spring native to create optimized production builds, apparently it has somehow intervened with the development build process of the application. For now, I have just removed it from my application.
Later on I will probably try to separate the development build.gradle from the production one.

SPRING JPA Lazy loading data to use in other class

I'm using Spring Boot for a project, I'm stuck with lazy loading.
What I want to do is load data in my controller, then send to presentable object, that will extract needed information and the JSON serializer do the bad work to create my custom HTTP response.
the problem occurs when the UserPresentation class calls the folder getter, the error is the well known: could not initialize proxy - no Session.
Of course the default fetch is LAZY for the folder and I want this, but I don't know how to prepare the object to be usable in the Presentation.
I copy-pasted only Folder set to be clear and short, but I've more collection inside User class, all of them give me the same problem.
I know that I could call getter in controller just to initialize Collections, but I find this like an hardcoding, in fact if I want add something to presentable I need to do in controller too.
I've tried too with #Transactional but not works.
Here are my class:
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "USER_ID")
private Integer id;
#Column(unique = true)
private String email;
private String password;
#Enumerated(EnumType.STRING)
private Authority userAuthority;
#OneToMany(mappedBy = "owner", cascade = CascadeType.ALL)
private Set<Folder> ownFolders = new HashSet<>();
... getter setter
}
#RestController
public class UserController {
#GetMapping(value = "/api/user", produces = APPLICATION_JSON_VALUE)
public CustomResponseEntity userInfo() {
User currentUser = loginService.getCurrentUser();
UserPresentation userPresentation = new UserPresentation(currentUser);
return ResponseManager.respondData(userPresentation);
}
}
public class UserPresentation implements Presentable {
private User user;
public UserPresentation(User user) {
this.user = user;
}
public Integer getId() {
return user.getId();
}
public String getEmail() {
return user.getUsername();
}
public String getAuthority() {
return user.getUserAuthority().name();
}
public boolean isEnabled() {
return user.isEnabled();
}
public Integer getOwnFolders() {
Set<Folder> folderList = user.getOwnFolders();
if (folderList == null)
return 0;
return folderList.size();
}
}
Last two just to be clear
public class ResponseManager {
// DATA
public static ResponseEntity respondData(Presentable presentable, String token) {
CustomResponse response = new DataResponse<>(presentable);
return new ResponseEntity<>(response, HttpStatus.OK);
}
}
public class DataResponse<T extends Presentable> extends CustomResponse {
private T data;
public T getData() {
return data;
}
private void setData(T data) {
this.data = data;
}
public DataResponse(T data) {
this.setData(data);
}
#Override
public String getType() {
return DATA;
}
}
I suppose you load the current user form the database with:
User currentUser = loginService.getCurrentUser();
and the getCurrentUser() method is transactional. You can either:
Use JPQL like this:
"select u from User u join fetch u.ownFolders where ... " to load the user's info (this way ownFolders relation is eagerly fetched)
or
Simply call user.getOwnFolders() inside getCurrentUser() to trigger
the fetch.
I found a way, even is a little bit dirty it allows me to do what I want without big change at the code.
Practically the problem occurs during the JSON serialization, that run outside of my control (somewhere inside Spring classes just before send HTTP response), so I manually serialized every Presentable object inside a #Transactional block just after its creation.
These are the changed classes:
public class UserPresentation implements Presentable {
private User user;
public UserPresentation(User user) {
this.user = user;
this.initialize() //ADDED (called here and in every other class that implements Presentable)
}
...getter and setter (which I want as JSON fields)
}
#RestController
public class UserController {
#Transactional //ADDED
#GetMapping(value = "/api/user", produces = APPLICATION_JSON_VALUE)
public CustomResponseEntity userInfo() {
User currentUser = loginService.getCurrentUser();
UserPresentation userPresentation = new UserPresentation(currentUser);
return ResponseManager.respondData(userPresentation);
}
}
Before this fix, the interface was used only to use Polymorfism inside ResponseManager, so was empty
public interface Presentable {
default void initialize() {
try {
new ObjectMapper().writeValueAsString(this);
} catch (JsonProcessingException e) {
throw new RuntimeJsonMappingException(e.getMessage());
}
}
}
I would suggest you use https://github.com/FasterXML/jackson-datatype-hibernate
The module supports datatypes of Hibernate versions 3.x , 4.x and 5.x; as well as some of the associated behavior such as lazy-loading and detection of transiency (#Transient annotation).
It knows how to handle Lazy loading after the session is closed , it will skip the json conversion for objects marked as Lazy fetch when outside session
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-hibernate5</artifactId>
<version>2.9.8</version>
</dependency>
ObjectMapper mapper = new ObjectMapper();
// for Hibernate 4.x:
mapper.registerModule(new Hibernate4Module());
// or, for Hibernate 5.x
mapper.registerModule(new Hibernate5Module());
// or, for Hibernate 3.6
mapper.registerModule(new Hibernate3Module());
#Configuration
public class WebMvcConfig implements WebMvcConfigurer {
/*
* Here we register the Hibernate4Module into an ObjectMapper, then set this * custom-configured ObjectMapper to the MessageConverter and return it to be * added to the HttpMessageConverters of our application
*/
public MappingJackson2HttpMessageConverter jacksonMessageConverter() {
MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
ObjectMapper hibernateAwareObjectMapper = new ObjectMapper();
hibernateAwareObjectMapper.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS);
hibernateAwareObjectMapper.enable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
// Registering Hibernate5Module to support lazy objects
hibernateAwareObjectMapper.registerModule(new Hibernate5Module());
messageConverter.setObjectMapper(hibernateAwareObjectMapper);
return messageConverter;
}
}
XML config
<mvc:annotation-driven>
<mvc:message-converters>
<!-- Use the HibernateAware mapper instead of the default -->
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="path.to.your.HibernateAwareObjectMapper" />
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>

Spring boot - setters on session scoped component not working from singleton service - fields are null

I have a simple service behind a REST controller in Spring Boot. The service is a singleton (by default) and I am autowiring a session-scoped bean component used for storing session preferences information and attempting to populate its values from the service. I call setters on the autowired component, but the fields I am setting stay null and aren't changed.
Have tried with and without Lombok on the bean; also with and without implementing Serializable on FooPref; also copying properties from FooPrefs to another DTO and returning it; also injecting via #Autowired as well as constructor injection with #Inject. The fields stay null in all of those cases.
Running Spring Boot (spring-boot-starter-parent) 1.5.6.RELEASE, Java 8, with the spring-boot-starter-web.
Session-scoped component:
#Component
#SessionScope(proxyMode = ScopedProxyMode.TARGET_CLASS)
#Data
#NoArgsConstructor
public class FooPrefs implements Serializable {
private String errorMessage;
private String email;
private String firstName;
private String lastName;
}
REST Controller:
#RestController
#RequestMapping("/api/foo")
public class FooController {
#Autowired
private FooPrefs fooPrefs;
private final FooService fooService;
#Inject
public FooController(FooService fooService) {
this.fooService = fooService;
}
#PostMapping(value = "/prefs", consumes = "application/json", produces = "application/json")
public FooPrefs updatePrefs(#RequestBody Person person) {
fooService.updatePrefs(person);
// These checks are evaluating to true
if (fooPrefs.getEmail() == null) {
LOGGER.error("Email is null!!");
}
if (fooPrefs.getFirstName() == null) {
LOGGER.error("First Name is null!!");
}
if (fooPrefs.getFirstName() == null) {
LOGGER.error("First Name is null!!");
}
return fooPrefs;
}
}
Service:
#Service
#Scope(value = "singleton")
#Transactional(readOnly = true)
public class FooService {
#Autowired
private FooPrefs fooPrefs;
#Inject
public FooService(FooRepository fooRepository) {
this.fooRepository = fooRepository;
}
public void updatePrefs(Person person) {
fooRepository.updatePerson(person);
//the fields below appear to getting set correctly while debugging in the scope of this method call but after method return, all values on fooPrefs are null
fooPrefs.setEmail(person.getEmail());
fooPrefs.setFirstName(person.getFirstName());
fooPrefs.setLastName(person.getLastName());
}
}
I discovered my problem. Fields were being added to my FooPrefs session-managed object and were breaking my client. The setters were actually working and being nulled out by some error handling code.
Edits per below fixed the JSON serialization problems:
Session-scoped component (no change)
New Dto
#Data
#NoArgsConstructor
public class FooPrefsDto {
private String errorMessage;
private String email;
private String firstName;
private String lastName;
}
Controller (updated)
#RestController
#RequestMapping("/api/foo")
public class FooController {
private final FooService fooService;
#Inject
public FooController(FooService fooService) {
this.fooService = fooService;
}
#PostMapping(value = "/prefs", consumes = "application/json", produces = "application/json")
public FooPrefsDto updatePrefs(#RequestBody Person person) {
FooPrefsDto result = fooService.updatePrefs(person);
// results coming back correctly now
if (result.getEmail() == null) {
LOGGER.error("Email is null!!");
}
if (result.getFirstName() == null) {
LOGGER.error("First Name is null!!");
}
if (result.getFirstName() == null) {
LOGGER.error("First Name is null!!");
}
return result;
}
}
Service (updated)
#Service
#Scope(value = "singleton")
#Transactional(readOnly = true)
public class FooService {
#Autowired
private FooPrefs fooPrefs;
#Inject
public FooService(FooRepository fooRepository) {
this.fooRepository = fooRepository;
}
public FooPrefsDto updatePrefs(Person person) {
fooRepository.updatePerson(person);
//the fields below appear to getting set correctly while debugging in the scope of this method call but after method return, all values on fooPrefs are null
fooPrefs.setEmail(person.getEmail());
fooPrefs.setFirstName(person.getFirstName());
fooPrefs.setLastName(person.getLastName());
return getFooPrefsDto();
}
private FooPrefsDto getFooPrefsDto() {
FooPrefsDto retDto = new FooPrefsDto();
retDto.setEmail(fooPrefs.getEmail());
retDto.setLastName(fooPrefs.getLastName());
retDto.setFirstName(fooPrefs.getFirstName());
return retDto;
}
}

How to map configuration objects to java object

I have a spring boot application which is using a spring cloud config.
How can i map a configuration element with some java object.
My config is something like this:
clients:
- id : 1
name: client 1
groups : [a,b]
- id : 2
name: client 2
groups : [a]
And my java object is:
public class ClientInfo {
private String clientId;
private List<String> profiles;
public ClientInfo(String clientId, List<String> pips) {
this.clientId = clientId;
this.profiles = pips;
}
public String getClientId() {
return clientId;
}
public void setClientId(String clientId) {
this.clientId = clientId;
}
public List<String> getProfiles() {
return profiles;
}
public void setProfiles(List<String> profiles) {
this.profiles = profiles;
}
}
I want to map my configuration with List
Use below code to configure configuration properties in to java Object,
#Component
#EnableConfigurationProperties
#ConfigurationProperties(prefix = "clients")
public class ClientInfo {
private String id;
private String name;
private List<String> groups;
public String getId(){ return id;}
public String getName(){ return name;}
public List<String> getGroups(){ return groups;}
}
Check following for example http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html
Inject this class in another class :
#Autowired
private ClientInfo clientInfo;
The above auto wiring will not work if the class is instantiated using "new operator".
Actually I found the reason why it was not working.
All that was needed is to have another class which contains a list of ClientInfo and have #EnableConfigurationProperties and #ConfigurationProperties annotations on it. This is because "clients" in my configuration is a list. After this change we can use #Autowired annotation to inject the configuration.

Resources