Unable to load application properties in springboot - spring-boot

I have application related properties in my spring boot application. The strange issue is sometimes the properties load without any issues but most of the times they throw an exception.
Here is my spring boot class annotated with #Configuration. Tried debugging the issue but could not find any reason for this weird behavior.
#Configuration
public class RedisConfig {
private static final Logger logger = LoggerFactory.getLogger(RedisConfig.class);
#Value("${redisurl}")
private String redisURL;
#Value("${redisport}")
private String redisPort;
#Bean
public JedisConnectionFactory redisConnectionFactory() {
logger.info("--redisURL-" + redisURL);
logger.info("--redisPort-" + redisPort);
JedisConnectionFactory redisConnectionFactory = new JedisConnectionFactory();
redisConnectionFactory.setHostName(redisURL);
redisConnectionFactory.setPort(Integer.parseInt(redisPort));
logger.info("--connected to redis--");
return redisConnectionFactory;
}
redisurl=cst-prd-007
redisport=6379
redispassword=
Any help is appreciated.
Stacktrace:
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.boot.actuate.autoconfigure.redis.RedisHealthIndicatorConfiguration': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'redisConfig': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'redisurl' in value "${redisurl}"
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:729)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:192)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1270)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1127)
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'redisurl' in value "${redisurl}"
at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:172)
at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:124)
at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:237)
at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:211)
at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.lambda$processProperties$0(PropertySourcesPlaceholderConfigurer.java:175)
at org.springframework.beans.factory.support.AbstractBeanFactory.resolveEmbeddedValue(AbstractBeanFactory.java:834)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1086)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1065)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:584)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:91)
at org.springframework.beans.factory.annotation.AutowiredAnnotationB
Edit:
I also tried doing this. Did not work
#Autowired
Environment env;
#Bean
public JedisConnectionFactory redisConnectionFactory() {
logger.info("--redisURL-" + redisURL);
logger.info("--redisPort-" + redisPort);
redisURL = env.getRequiredProperty("redis.url");
redisPort = env.getRequiredProperty("redis.port");
JedisConnectionFactory redisConnectionFactory = new JedisConnectionFactory();
redisConnectionFactory.setHostName(redisURL);
redisConnectionFactory.setPort(Integer.parseInt(redisPort));
logger.info("--connected to redis--");
return redisConnectionFactory;
}
Issue solved after using the below approach
#Component
public class RedisConf {
#Value("${redis.url}")
String url;
#Value("${redis.port}")
int port;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
}

Instead of using #Value annotation, you can try using Environment from Spring Framework API.
Like this,
#Configuration
public class RedisConfig {
private static final Logger logger = LoggerFactory.getLogger(RedisConfig.class);
private String redisURL, redisPort;
#Autowired
private Environment env;
#Bean
public JedisConnectionFactory redisConnectionFactory() {
redisURL = env.getRequiredProperty("redisurl");
redisPort = env.getRequiredProperty("redisport");
JedisConnectionFactory redisConnectionFactory = new JedisConnectionFactory();
redisConnectionFactory.setHostName(redisURL);
redisConnectionFactory.setPort(Integer.parseInt(redisPort));
logger.info("--connected to redis--");
return redisConnectionFactory;
}

The issue is solved after using the below approach
#Component
public class RedisConf {
#Value("${redis.url}")
String url;
#Value("${redis.port}")
int port;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
}

Related

org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type

2020-09-23T15:28:00.3483912Z java.lang.IllegalStateException: Failed to load ApplicationContext
2020-09-23T15:28:00.3489821Z Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'salecChannelEventProcessor' defined in file [/home/runner/work/calculation-service/calculation-service/target/classes/com/demo/calculation/saleschannel/SalecChannelEventProcessor.class]: Unsatisfied dependency expressed through constructor parameter 1; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'de.demo.json.schema.JsonValidator' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations:
import de.demo.json.schema.JsonValidator;
#Configuration
#ComponentScan( basePackages = {
"com.demo",
"de.demo" },
excludeFilters = {
#ComponentScan.Filter( Configuration.class )
} )
#ImportResource("classpath:/spring-context.xml")
#Import({SwaggerConfig.class, SalesChannelSqsConfig.class})
public class SpringMvcConfig extends WebMvcConfigurationSupport {
#Autowired private ApplicationContext applicationContext;
#Bean( name = "objectMapper" )
public ObjectMapper getObjectMapper( JacksonService jacksonService ) {
return jacksonService.getObjectMapper();
}
#Bean(name = "jsonValidator")
public JsonValidator jsonValidator() {
return new JsonValidator();
}
}
#Component
#Slf4j
#RequiredArgsConstructor
public class SalesChannelUpdateListerner {
#NonNull
private final SalesChannelService salesChannelService;
#NonNull
private final SalecChannelEventProcessor salecChannelEventProcessor;
#SqsListener(value = "${sales.channel.update.queue.name}", deletionPolicy = ON_SUCCESS)
#SneakyThrows
public void receiveSalesChannelUpdateEvent(
#NotificationMessage EnvelopedMessage envelopedMessage) {
log.debug("Received message from sales channel update event queue : {}"
}
#Component
#Slf4j
#RequiredArgsConstructor
public class SalecChannelEventProcessor {
private static final String MESSAGE_TYPE = "sales_channel_update";
#NonNull
private final ObjectMapper objectMapper;
#NonNull
private final JsonValidator jsonValidator;
#SneakyThrows(JsonProcessingException.class)
public boolean isValid(EnvelopedMessage envelopedMessage) {
if (!MESSAGE_TYPE.equals(envelopedMessage.getType())) {
return false;
}
return jsonValidator.validate(envelopedMessage);
}
You need to create the JsonValidator bean. You need to change yor SalecChannelEventProcessor to be:
#Component
#Slf4j
#RequiredArgsConstructor
public class SalecChannelEventProcessor {
private static final String MESSAGE_TYPE = "sales_channel_update";
#NonNull
private final ObjectMapper objectMapper;
#Bean
public JsonValidator jsonValidator(){
return new JsonValidator();
}
#SneakyThrows(JsonProcessingException.class)
public boolean isValid(EnvelopedMessage envelopedMessage) {
if (!MESSAGE_TYPE.equals(envelopedMessage.getType())) {
return false;
}
return jsonValidator().validate(envelopedMessage);
}
}

Set Spring SolrDocument Collection name based on PropertyValue

I want to set values Spring SolrDocument Collection based on application.yml value.
#Data
#SolrDocument(collection = #Value("${solr.core}"))
public class SearchableProduct {
}
Hoi Michela,
Ok, I had the same Problem and I found a solution: SpEL
it is described in details here:Spring Data for Apache Solr
you have to add the EL-expression to the Annotation
#SolrDocument(collection = "#{#serverSolrContext.getCollectionName()}")
public class SOLREntity implements Serializable {
.....
}
you have to provide a the serverSolrContext Bean with the method getCollectionName().
#Value("${solr.core}")
private String core;
public String getCollectionName() {
return core;
}
you have to write in our application.properties the following core entry.
solr.core=myOwnCoreName
That's it actually, BUT
if you get the following Exception, so as I did:
org.springframework.expression.spel.SpelEvaluationException: EL1057E: No bean resolver registered in the context to resolve access to bean
You have to have the following in your Configuration Bean
#Configuration
#EnableSolrRepositories(basePackages = { "de.solr.db" })
#Profile("default")
#PropertySource("classpath:application.properties")
public class ServerSolrContext extends AbstractSolrConfiguration {
private static final Logger logger = LoggerFactory.getLogger(ServerSolrContext.class);
#Resource
private Environment environment;
#Value("${solr.core}")
private String core;
public String getCollectionName() {
return core;
}
#PostConstruct
public void init() {
System.out.println(core);
}
#Bean
public SolrClient solrClient() {
String url = environment.getProperty("solr.server.url");
String user = environment.getProperty("solr.server.user");
String password = environment.getProperty("solr.server.password");
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT),
new UsernamePasswordCredentials(user, password));
SSLContext sslContext = null;
try {
sslContext = ReportConfiguration.getTrustAllContext();
}
catch (KeyManagementException | NoSuchAlgorithmException e) {
e.printStackTrace();
}
LayeredConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext);
HttpClient httpClient = HttpClientBuilder.create().setSSLSocketFactory(sslSocketFactory)
.addInterceptorFirst(new PreemptiveAuthInterceptor()).setDefaultCredentialsProvider(credentialsProvider)
.build();
SolrClient client = new HttpSolrClient.Builder().withHttpClient(httpClient).withBaseSolrUrl(url).build();
return client;
}
#Bean
#ConditionalOnMissingBean(name = "solrTemplate")
public SolrTemplate solrTemplate(#Qualifier("mySolrTemplate") SolrTemplate solrTemplate) {
return solrTemplate;
}
#Bean("mySolrTemplate")
public SolrTemplate mySolrTemplate(SolrClient solrClient, SolrConverter solrConverter) {
return new SolrTemplate(new HttpSolrClientFactory(solrClient), solrConverter);
}
#Override
public SolrClientFactory solrClientFactory() {
return new HttpSolrClientFactory(solrClient());
}
}
The last 3 Methods are doing the Trick, that cost me a while to find the right solution:
it is here, so actually I was lucky to find this:
Allow PropertyPlaceholders in #SolrDocument solrCoreName

Unit Test Error creating bean with name "amqAdmin" while testing spring integration TCP component

I'm writing a sidecar micro service that talks TCP to a legacy app and uses rabbitMQ on the other side. I'm just getting started and writing tests as I go along to better understand how everything works as I'm new to Spring. My app builds, deploys, and runs fine.
However, writing clean tests has been a bit more complicated. I have been patterning my code off the spring-integration tcp basic examples. I started with having a mock TCPServer to test my code defined outside my test class. But the mock TCPServer kept being built for every test class. So I moved it into the TCPGatewayTest class similar to the example I found.
This led to some missing bean issues which led me to add a #ContextConfiguration annotation which has gotten me further. But now I have other missing beans. I'm sure I'm messing up my ApplicationContext with #ContextConfiguration. Is there a better way of doing this with a different annotation or doing it slightly different? I'm not going the xml route and would like to steer clear of it if possible.
The familiar no qualifying bean error:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.amqp.rabbit.connection.ConnectionFactory' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
My Test Class is the following
package org.inc.imo;
#ComponentScan("org.inc")
#ContextConfiguration(classes = {TCPGatewayTest.TCPServerMock.class,
org.inc.imo.Configuration.TCPConfig.class,
org.inc.imo.Configuration.RabbitConfig.class })
#TestPropertySource(locations= "classpath:test.properties")
#RunWith(SpringRunner.class)
#SpringBootTest
public class TCPGatewayTest {
#Autowired
private TCPGateway gateway;
#Autowired
AbstractServerConnectionFactory crLfServer;
#Before
public void setup() {
TestingUtilities.waitListening(this.crLfServer, 10000L);
}
#Test
public void testConnectionToMockServer() {
String result = gateway.send("Hello World");
assertEquals("HELLO WORLD", result);
}
#Configuration
#MessageEndpoint
public static class TCPServerMock {
#Value("${imo.port}")
private int port;
#Bean()
public AbstractServerConnectionFactory serverCF() {
return new TcpNetServerConnectionFactory(this.port);
}
#Transformer(inputChannel="fromTcp", outputChannel="toEcho")
public String convert(byte[] bytes) {
return new String(bytes);
}
#ServiceActivator(inputChannel="toEcho")
public String upCase(String in) {
return in.toUpperCase();
}
#Bean
public TcpInboundGateway tcpInGate(AbstractServerConnectionFactory connectionFactory) {
TcpInboundGateway inGate = new TcpInboundGateway();
inGate.setConnectionFactory(connectionFactory);
inGate.setRequestChannel(fromTcp());
return inGate;
}
#Bean
public MessageChannel fromTcp() {
return new DirectChannel();
}
}
}
Rabbit Config Class
package org.inc.imo.configuration;
#EnableIntegration
#IntegrationComponentScan
#ComponentScan
#Configuration
public class RabbitConfig {
public final static String IMO_REQUEST_JEA = "imo.request.jea";
public final static String IMO_REQUEST_INFO = "imo.request.info";
#Bean
public AmqpAdmin amqpAdmin(final ConnectionFactory connectionFactory) {
RabbitAdmin admin = new RabbitAdmin(connectionFactory);
admin.declareQueue(jeaRequestQueue());
admin.declareQueue(infoRequestQueue());
return admin;
}
#Bean
public Queue jeaRequestQueue() {
return new Queue(IMO_REQUEST_JEA);
}
#Bean
public Queue infoRequestQueue() {
return new Queue(IMO_REQUEST_INFO);
}
#Bean
public RabbitTemplate rabbitTemplate(final ConnectionFactory connectionFactory) {
RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());
return rabbitTemplate;
}
#Bean
public ObjectWriter objectWriter() {
return new ObjectMapper().writer();
}
}
TCPConfig class
package org.inc.imo.configuration;
#EnableIntegration
#IntegrationComponentScan
#ComponentScan
#Configuration
public class TCPConfig {
#Value("${imo.hostname}")
private String host;
#Value("${imo.port}")
private int port;
private static MessageChannel sendChannel;
private static MessageChannel replyChannel;
#Bean
public MessageChannel replyChannel() {
replyChannel = new DirectChannel();
return replyChannel;
}
#Bean(name="sendChannel")
public MessageChannel sendChannel() {
MessageChannel directChannel = new DirectChannel();
sendChannel = directChannel;
return directChannel;
}
#Bean
public TcpNetClientConnectionFactory connectionFactory() {
TcpNetClientConnectionFactory connectionFactory = new TcpNetClientConnectionFactory(host, port);
connectionFactory.setSingleUse(false);
return connectionFactory;
}
#Bean
#ServiceActivator(inputChannel = "sendChannel")
public TcpOutboundGateway tcpOutboundGateway() {
TcpOutboundGateway tcpOutboundGateway = new TcpOutboundGateway();
tcpOutboundGateway.setConnectionFactory(connectionFactory());
tcpOutboundGateway.setReplyChannel(this.replyChannel());
tcpOutboundGateway.setRequiresReply(true);
return tcpOutboundGateway;
}
}
TCPGateway Interface
package org.inc.imo.Domain;
#MessagingGateway(defaultRequestChannel = "sendChannel")
public interface TCPGateway {
String send(String message);
}
The exception is like:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.amqp.rabbit.connection.ConnectionFactory' available: expected at least 1 bean which qualifies as autowire candidate.
And the suffered bean is like:
#Bean
public AmqpAdmin amqpAdmin(final ConnectionFactory connectionFactory) {
RabbitAdmin admin = new RabbitAdmin(connectionFactory);
admin.declareQueue(jeaRequestQueue());
admin.declareQueue(infoRequestQueue());
return admin;
}
So, you request here org.springframework.amqp.rabbit.connection.ConnectionFactory bean injection, but there is no one.
If you simply test against the local RabbitMQ, there is just enough to add one more bean:
#Bean
ConnectionFactory connectionFactory() {
return new CachingConnectionFactory();
}
and your AmqpAdmin will be able to connect there.

Spring: Cannot autowire beans from parent context

I have a Spring Boot (1.4.0) application, which, during initialization, starts a 2nd context (I need that because I have to publish a web service using a specific kind of authorization while the parent context publishes a different service).
I created a child context like so:
#Configuration
#ConditionalOnClass({Servlet.class, DispatcherServlet.class})
#ConditionalOnWebApplication
public class ChildContextConfiguration implements ApplicationContextAware, ApplicationListener<ContextRefreshedEvent> {
private final Logger logger = LoggerFactory.getLogger(ChildContextConfiguration.class);
private ApplicationContext applicationContext;
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
private void createChildContext() {
final AnnotationConfigEmbeddedWebApplicationContext childContext = new AnnotationConfigEmbeddedWebApplicationContext(ChildConfiguration.class);
childContext.setParent(this.applicationContext);
childContext.setId(this.applicationContext.getId() + ":child");
}
#Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
logger.info("creating child context");
createChildContext();
}
}
The child context's configuration class looks like this:
#Configuration
#ComponentScan(basePackages = {"com.example.child"})
#PropertySource("file:some-config.properties")
#ConfigurationProperties(prefix = "child")
#EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
public class ChildConfiguration {
private Integer port;
private String keyStore;
private String keyStorePass;
private String keyPass;
private String trustStore;
private String trustStorePass;
private String packageBase;
public void setPort(Integer port) {
this.port = port;
}
public void setKeyStore(String keyStore) {
this.keyStore = keyStore;
}
public void setKeyStorePass(String keyStorePass) {
this.keyStorePass = keyStorePass;
}
public void setKeyPass(String keyPass) {
this.keyPass = keyPass;
}
public void setTrustStore(String trustStore) {
this.trustStore = trustStore;
}
public void setTrustStorePass(String trustStorePass) {
this.trustStorePass = trustStorePass;
}
public void setPackageBase(String packageBase) {
this.packageBase = packageBase;
}
#Bean
public Jaxb2Marshaller swpMarshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setPackagesToScan(packageBase);
return marshaller;
}
#Bean
public Unmarshaller swpUnmarshaller() throws JAXBException {
JAXBContext jaxbContext = JAXBContext.newInstance(packageBase);
return jaxbContext.createUnmarshaller();
}
#Bean
public Filter encodingFilter() {
CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
encodingFilter.setEncoding("UTF-8");
return encodingFilter;
}
#Bean
public ServerProperties serverProperties() {
ServerProperties props = new ServerProperties();
props.setPort(port);
props.setSsl(ssl());
return props;
}
private Ssl ssl() {
Ssl ssl = new Ssl();
ssl.setEnabled(true);
ssl.setKeyStore(keyStore);
ssl.setKeyStorePassword(keyStorePass);
ssl.setKeyStoreType("JKS");
ssl.setKeyPassword(keyPass);
ssl.setTrustStore(trustStore);
ssl.setTrustStorePassword(trustStorePass);
ssl.setClientAuth(Ssl.ClientAuth.NEED);
return ssl;
}
}
So far, this works. But when I try to autowire a bean from the parent context, I get an error stating that there is no candidate.
Another interesting thing is, when I inject the (child)context into one of my child context's beans using the ApplicationContextAware interface, the getParent() property of that context is null at that time.
What I have done now is implementing getter functions like these:
private SomeBean getSomeBean() {
if (this.someBean == null) {
this.someBean = applicationContext.getParent().getBean(SomeBean.class);
}
return this.someBean;
}
To summarize this: During construction of the child context's beans, the parent context is not set, so I cannot use autowire.
Is there some way to make autowire work with my setup?
Constructor taking classes to register refreshes context internally - try to set class and refresh manually after setting parent context.
private void createChildContext() {
final AnnotationConfigEmbeddedWebApplicationContext childContext = new AnnotationConfigEmbeddedWebApplicationContext();
childContext.setParent(this.applicationContext);
childContext.setId(this.applicationContext.getId() + ":child");
childContext.register(ChildConfiguration.class);
childContext.refresh();
}

spring injection issues with spring data

I am getting the following error
Error creating bean with name 'genericRepository': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalArgumentException: Not an managed type: class java.lang.Object
I am new to generics, if there are any generics issue please let me know as well
my Contact.java is in com.merc.template.managelistofobjects.domain package
All other classes are in com.merc.template.managelistofobjects package
ContactCollectionManagerImpl
#Component
public class ContactCollectionManagerImpl extends CollectionManagerImpl<Contact> implements CollectionManager<Contact>{
#Autowired
private GenericRepository<Contact,Long> genericRepository;
public ContactCollectionManagerImpl() {
setGenericRepository(genericRepository);
}
#Override
public void addToCollection(Contact contact, boolean reload){
super.addToCollection(contact, entityDataMap, reload);
}
}
CollectionManagerImpl
public abstract class CollectionManagerImpl<T extends EntityBean> implements CollectionManager<T>{
private GenericRepository objectManager;
public void setGenericRepository(GenericRepository genericRepository) {
this.objectManager = genericRepository;
}
protected void addToCollection(T entity, Map<Long,T> entityDataMap, boolean reload) {
//reload is set to false when the static map needs not be updated
if(reload){
//loads all the existing collection objects from db
loadCollection(entityDataMap, false);
//check if the obect to be inserted already exists in collection
if(entityDataMap.containsKey(entity.getId())){
return;
}
}
//TODO save to database
objectManager.save(entity);
if(reload){
syncCollectionWithDB(entityDataMap);
}
}
}
CollectionManager
public interface CollectionManager<T> {
public void addToCollection(T object, boolean reload);
}
GenericRepository
public interface GenericRepository<T, ID extends Long> extends JpaRepository<T, ID>{
}
MyApplicationContext
#Configuration
#EnableJpaRepositories
#ComponentScan("com.merc.template.managelistofobjects")
#ImportResource("classpath:spring/app-context.xml")
#PropertySource("classpath:application.properties")
public class MyApplicationContext {
private static final String PROPERTY_NAME_DATABASE_DRIVER = "db.driver";
private static final String PROPERTY_NAME_DATABASE_PASSWORD = "db.password";
private static final String PROPERTY_NAME_DATABASE_URL = "db.url";
private static final String PROPERTY_NAME_DATABASE_USERNAME = "db.username";
private static final String PROPERTY_NAME_HIBERNATE_DIALECT = "hibernate.dialect";
private static final String PROPERTY_NAME_HIBERNATE_FORMAT_SQL = "hibernate.format_sql";
private static final String PROPERTY_NAME_HIBERNATE_NAMING_STRATEGY = "hibernate.ejb.naming_strategy";
private static final String PROPERTY_NAME_HIBERNATE_SHOW_SQL = "hibernate.show_sql";
private static final String PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN = "entitymanager.packages.to.scan";
#Resource
private Environment environment;
#Bean
public DataSource dataSource() {
BoneCPDataSource dataSource = new BoneCPDataSource();
dataSource.setDriverClass(environment.getRequiredProperty(PROPERTY_NAME_DATABASE_DRIVER));
dataSource.setJdbcUrl(environment.getRequiredProperty(PROPERTY_NAME_DATABASE_URL));
dataSource.setUsername(environment.getRequiredProperty(PROPERTY_NAME_DATABASE_USERNAME));
dataSource.setPassword(environment.getRequiredProperty(PROPERTY_NAME_DATABASE_PASSWORD));
return dataSource;
}
#Bean
public JpaTransactionManager transactionManager() throws ClassNotFoundException {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactoryBean().getObject());
return transactionManager;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() throws ClassNotFoundException {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSource());
//setPackagesToScan = com.merc.template.managelistofobjects.domain
entityManagerFactoryBean.setPackagesToScan(environment.getRequiredProperty(PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN));
entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistence.class);
Properties jpaProterties = new Properties();
jpaProterties.put(PROPERTY_NAME_HIBERNATE_DIALECT, environment.getRequiredProperty(PROPERTY_NAME_HIBERNATE_DIALECT));
jpaProterties.put(PROPERTY_NAME_HIBERNATE_FORMAT_SQL, environment.getRequiredProperty(PROPERTY_NAME_HIBERNATE_FORMAT_SQL));
jpaProterties.put(PROPERTY_NAME_HIBERNATE_NAMING_STRATEGY, environment.getRequiredProperty(PROPERTY_NAME_HIBERNATE_NAMING_STRATEGY));
jpaProterties.put(PROPERTY_NAME_HIBERNATE_SHOW_SQL, environment.getRequiredProperty(PROPERTY_NAME_HIBERNATE_SHOW_SQL));
entityManagerFactoryBean.setJpaProperties(jpaProterties);
return entityManagerFactoryBean;
}
#Bean
public CollectionManager contactCollectionManager(){
return new ContactCollectionManagerImpl();
}
}
My main class contains the following code
ApplicationContext context = new AnnotationConfigApplicationContext(MyApplicationContext.class);
CollectionManager collMgr = context.getBean("contactCollectionManager",CollectionManager.class);
Contact contact = new Contact(2L,"xyz","abc");
collMgr.addToCollection(contact, true);
entitymanager.packages.to.scan=com.merc.template.managelistofobjects.domain
my spring xml file contains just one line
<jpa:repositories base-package="com.merc.template.managelistofobjects"/>
When i run the code I get the following error
java.lang.IllegalArgumentException: Not an managed type: class java.lang.Object
You cannot autowire an object that takes an generic type, You will have to define a strongly typed sub interface of GenericRepository and then autowire it inside your clases
public interface ContactGenericRepository extends GenericRepository<Contact,Long> {}
Then autowire the new interface
#Autowired
private ContactGenericRepository contractGenericRepository;
P.S: you cannot use the autowired object inside the constructor of the class that wrap it, as you are doing inside the ContactCollectionManagerImpl constructor, as the object is not instantiated yet
You could easily use #PostConstruct on any other method that does that behaviour you want, like this
#PostConstruct
public void populateContactCollectionManagerImpl() {
setGenericRepository(genericRepository);
}

Resources