Basic Spring JDBC application, JdbcTemplate bean not found - spring

A bean definition of type org.springframework.jdbc.core.JdbcTemplate was not found, therefore #Autowired private JdbcTemplate jdbcTemplate; doesn't actually have a value inside it.
My Application.java looks as following:
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Value("${spring.name}")
private String name;
#Autowired
private JdbcTemplate jdbcTemplate;
private static final Logger log = LoggerFactory.getLogger(Application.class);
// #Bean
// public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
// return args -> {
// System.out.printf("The application is running %s!", name);
// };
// }
public void run(String... strings) throws Exception {
log.info("Creating tables");
jdbcTemplate.execute("DROP TABLE customers IF EXISTS");
jdbcTemplate.execute("CREATE TABLE customers(" +
"id SERIAL, first_name VARCHAR(255), last_name VARCHAR(255))");
// Split up the array of whole names into an array of first/last names
List<Object[]> splitUpNames = Arrays.asList("John Woo", "Jeff Dean", "Josh Bloch", "Josh Long").stream()
.map(name -> name.split(" "))
.collect(Collectors.toList());
// Use a Java 8 stream to print out each tuple of the list
splitUpNames.forEach(name -> log.info(String.format("Inserting customer record for %s %s", name[0], name[1])));
// Uses JdbcTemplate's batchUpdate operation to bulk load data
jdbcTemplate.batchUpdate("INSERT INTO customers(first_name, last_name) VALUES (?,?)", splitUpNames);
log.info("Querying for customer records where first_name = 'Josh':");
jdbcTemplate.query(
"SELECT id, first_name, last_name FROM customers WHERE first_name = ?", new Object[] { "Josh" },
(rs, rowNum) -> new CustomerModel(rs.getLong("id"), rs.getString("first_name"), rs.getString("last_name"))
).forEach(customer -> log.info(customer.toString()));
}
I understand Dependency Injection and IoC which should technically instantiate a JdbcTemplate instance by itself, but if I do it manually it I have the following code which gives the error that JdbcTemplate bean requires dataSource property (which I'm giving as below):
#Value("${spring.datasource.url}")
private String dbUrl;
#Value("${spring.datasource.username}")
private String dbUsername;
#Value("${spring.datasource.password}")
private String dbPassword;
private DataSource dataSource = new DriverManagerDataSource(dbUrl, dbUsername, dbPassword);
private JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);

These lines are not producing Spring beans, so they are not candidates for autowiring:
private DataSource dataSource = new DriverManagerDataSource(dbUrl, dbUsername, dbPassword);
private JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
If you're using Spring Boot, you can follow these instructions to configure your datasource, though make sure you use the spring-boot-starter-jdbc dependency in your pom.
If you're configuring these manually, you need to create a #Configuration class, that exposes both a DataSource and JdbcTemplate bean. For example, something like:
#Configuration
public class DatabaseConfiguration {
#Value("${spring.datasource.url}")
private String dbUrl;
#Value("${spring.datasource.username}")
private String dbUsername;
#Value("${spring.datasource.password}")
private String dbPassword;
#Bean
public DataSource dataSource() {
return new DriverManagerDataSource(dbUrl, dbUsername, dbPassword);
}
#Bean
public JdbcTemplate jdbcTemplate() {
return new JdbcTemplate(dataSource);
}
}

Related

Initialize datasource bean on condition

So, I need to make an initialization of DataSource by condition. I take all the db-config data from the .env file, where there is a special variable spring_profiles_active. When this variable is equal to "p2" I need to initialize secondDataSource, otherwise not. How do I do this?
My configuration:
#Configuration
public class JpaConfig {
#Value("${jdbc.url}")
private String jdbcUrl;
#Value("${jdbc.username}")
private String jdbcUsername;
#Value("${jdbc.password}")
private String jdbcPassword;
#Value("${jdbc.driverClassName}")
private String jdbcDriverClassName;
#Value("${second.jdbc.url}")
private String secondJdbcUrl;
#Value("${second.jdbc.username}")
private String secondJdbcUsername;
#Value("${second.jdbc.password}")
private String secondJdbcPassword;
#Value("${second.jdbc.driverClassName}")
private String secondJdbcDriverClassName;
#Bean
#Primary
public DataSource dataSource(){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(jdbcDriverClassName);
dataSource.setUrl(jdbcUrl);
dataSource.setUsername(jdbcUsername);
dataSource.setPassword(EncryptionUtil.decryptProperty(jdbcPassword));
return dataSource;
}
#Bean
#Qualifier("secondDataSource")
public DataSource secondDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(secondJdbcDriverClassName);
dataSource.setUrl(secondJdbcUrl);
dataSource.setUsername(secondJdbcUsername);
dataSource.setPassword(EncryptionUtil.decryptProperty(secondJdbcPassword));
return dataSource;
}
#Bean
#Primary
public JdbcTemplate jdbcTemplate() { return new JdbcTemplate(dataSource()); }
#Bean
#Qualifier("secondJdbcTemplate")
public JdbcTemplate secondJdbcTemplate(#Qualifier("secondDataSource") DataSource secondDataSource) {
return new JdbcTemplate(secondDataSource);
}
}
update:
I try to do this with #Condition annotation, but get an exception java.lang.NullPointerException: null in return activeProfile.equals("p2"). code:
#Configuration
#Conditional(SecondJpaConfigCondition.class)
public class SecondJpaConfig {
#Value("${second.jdbc.url}")
private String secondJdbcUrl;
#Value("${second.jdbc.username}")
private String secondJdbcUsername;
#Value("${second.jdbc.password}")
private String secondJdbcPassword;
#Value("${second.jdbc.driverClassName}")
private String secondJdbcDriverClassName;
#Bean
#Qualifier("secondDataSource")
public DataSource secondDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(secondJdbcDriverClassName);
dataSource.setUrl(secondJdbcUrl);
dataSource.setUsername(secondJdbcUsername);
dataSource.setPassword(EncryptionUtil.decryptProperty(secondJdbcPassword));
return dataSource;
}
#Bean
#Qualifier("secondJdbcTemplate")
public JdbcTemplate secondJdbcTemplate(#Qualifier("secondDataSource") DataSource secondDataSource) {
return new JdbcTemplate(secondDataSource);
}
}
#Component
public class SecondJpaConfigCondition implements Condition {
#Value("${spring.profiles.active}")
private String activeProfile;
#Override
public boolean matches(ConditionContext arg0, AnnotatedTypeMetadata arg1) {
return activeProfile.equals("p2");
}
}
I recommend you to use the #ConditionalOnProperty annotation. It can be used on the class or a method with the #Bean annotation. I would separate the configuration of the two databases in two different classes (it's not mandatory, you could us the annotion over the secondDataSource and secondJdbcTemplate methods) and do something like this:
JpaConfig (First Datasource):
#Configuration
public class JpaConfig {
#Value("${jdbc.url}")
private String jdbcUrl;
#Value("${jdbc.username}")
private String jdbcUsername;
#Value("${jdbc.password}")
private String jdbcPassword;
#Value("${jdbc.driverClassName}")
private String jdbcDriverClassName;
#Bean
#Primary
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(jdbcDriverClassName);
dataSource.setUrl(jdbcUrl);
dataSource.setUsername(jdbcUsername);
dataSource.setPassword(EncryptionUtil.decryptProperty(jdbcPassword));
return dataSource;
}
#Bean
#Primary
public JdbcTemplate jdbcTemplate() {
return new JdbcTemplate(dataSource());
}
}
JpaConditionalConfig (Second Datasource):
#Configuration
#ConditionalOnProperty(prefix = "cond", name = "spring_profiles_active", havingValue = "p2")
public class JpaOptionalConfig {
#Value("${second.jdbc.url}")
private String secondJdbcUrl;
#Value("${second.jdbc.username}")
private String secondJdbcUsername;
#Value("${second.jdbc.password}")
private String secondJdbcPassword;
#Value("${second.jdbc.driverClassName}")
private String secondJdbcDriverClassName;
#Bean
#Qualifier("secondDataSource")
public DataSource secondDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(secondJdbcDriverClassName);
dataSource.setUrl(secondJdbcUrl);
dataSource.setUsername(secondJdbcUsername);
dataSource.setPassword(EncryptionUtil.decryptProperty(secondJdbcPassword));
return dataSource;
}
#Bean
#Qualifier("secondJdbcTemplate")
public JdbcTemplate secondJdbcTemplate(#Qualifier("secondDataSource") DataSource secondDataSource) {
return new JdbcTemplate(secondDataSource);
}
}
Properties file where is defined the spring_profiles_active property, which will be read by Spring to know if the conditional beans should be created:
jdbc.url=jdbc:h2:mem:mydb
jdbc.username=sa
jdbc.password=password
jdbc.driverClassName=org.h2.Driver
second.jdbc.url=jdbc:h2:mem:mydb
second.jdbc.username=sa
second.jdbc.password=password
second.jdbc.driverClassName=org.h2.Driver
#THIS IS THE PROPERTY USED IN THE CONDITIONAL BEANS
conditional.spring_profiles_active=p2

Spring jdbcTemplate NPE exception [duplicate]

This question already has answers here:
Why is my Spring #Autowired field null?
(21 answers)
Closed 2 years ago.
I am trying to use the jdbcTemplate to query a MySQL database to get the SYSDATE. So the query is as simple as SELECT SYSDATE()
However, I get the following error:
Exception in thread "main" java.lang.NullPointerException
at com.trade.xml.modifier.Test.<init>(Test.java:18)
at com.trade.xml.modifier.TradeModifierApplication.main(TradeModifierApplication.java:17)
Here is a bit of what I do:
I created a DatabaseConfiguration.class which should take all the connection details from the application.properties
The application.properties looks like this:
spring.datasource.url=jdbc:mysql://localhost:3306/xmlconverter
spring.datasource.username=root
spring.datasource.password=
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MariaDBDialect
The DatabaseConfiguration.class looks like this
#Configuration
public class DatabaseConfiguration {
#Value("${spring.datasource.driver-class-name}")
private String driverName;
#Value("${spring.datasource.url}")
private String url;
#Value("${spring.datasource.username}")
private String userName;
#Value("${spring.datasource.password}")
private String password;
#Bean(name = "dataSource")
public DataSource dataSource() {
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(driverName);
dataSource.setUrl(url);
dataSource.setUsername(userName);
dataSource.setPassword(password);
return dataSource;
}
#Bean
public JdbcTemplate dbjdbcTemplate() {
return new JdbcTemplate(dataSource());
}
}
2.I also created a Test.class where I wrote my method for querying
#Service
public class Test {
//Since a bean is created in DatabaseConfiguration,
//"template = new JdbcTemplate()" is omitted (should be recognized automatically, right?)
#Autowired
private JdbcTemplate template;
public String getDate() {
String sql = "SELECT SYSDATE()";
return template.queryForObject(sql, String.class);
}
}
The main class looks as follows
#SpringBootApplication
public class TradeModifierApplication {
public static void main(String[] args) {
SpringApplication.run(TradeModifierApplication.class, args);
Test test = new Test();
System.out.println(test.getDate());
At this point I have read the whole Internet and I am not sure what is the root cause of this NPE. Any help/hints will be appreciated.
The problem should be this line in TradeModifierApplication:
Test test = new Test();
You should let the spring container to instance Test class.
One way would be to inject by:
public static void main(String[] args) {
ApplicationContext applicationContext = SpringApplication.run(TradeModifierApplication.class, args);
Test service = applicationContext.getBean(Test.class);
service.getDate());
}
}

Spring boot common application properties

Spring boot application properties needs to follow convention from https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html when we use any DB like cassandra/mongo. In case if we want to declare our own properties for DB setup instead of spring-boot convention, what are all the steps we need to do for setting up DB?
You can do this: Spring boot - custom variables in Application.properties
or you can just create your own property in your application.properties file like:
my.property.someDb.hostname=http://wherever.comand then reference to it in your code like:
#Value("${my.property.someDb.hostname}")
private String someDbHostname;
Update 1:
If you want to create the MongoDb with your own properties you have to define the right Java Beans in an #Configuration file. For MongoDB it could look like the following:
#Configuration
public class MyMongoConfig extends AbstractMongoConfiguration{
#Value("${my.property.someDb.hostname}")
private String someDbHostname;
#Value("${my.property.someDb.myOwnPortDefinition}")
private int myOwnPortDefinition;
#Value("${my.property.someDb.myDatabasename}")
private String myDatabasename;
#Override
protected String getDatabaseName() {
return myDatabasename;
}
#Override
#Bean
public Mongo mongo() throws Exception{
return new MongoClient(someDbHostname, myOwnPortDefinition );
}
#Bean
public MongoTemplate mongoTemplate() throws Exception{
return new MongoTemplate(mongo(), getDatabaseName());
}
}
These are the essential steps you need in order to get a data source like Jdbc, mongodb set up in Spring Boot
Need a #Configuration class that has transaction management enabled
on it
Read the environment properties for the datasource i.e. dataSource
url, username, password etc.
Create beans for datasource, session factory, transaction manager
etc.
Once all of the above setup, use this #Configuration in your
consumer to initialize the spring application context
Here are some snippets of wiring mongodb datasource in spring boot
DataSourceConfiguration.java
#Configuration
#EnableTransactionManagement
#ComponentScan(basePackages = {"com.example.xyz"})
public class DatabaseEntityConfiguration {
public static final String DATABASE_ENTITY_DATA_SOURCE = "databaseDataSource";
public static final String DATABASE_HIBERNATE_PROPERTIES = "databaseHibernateProperties";
public static final String DATABASE_ENTITY_SESSION_FACTORY = "databaseSessionFactory";
public static final String DATABASE_ENTITY_TRANSACTION_MANAGER = "databaseTransactionManager";
public static final String DATABASE_ENTITY_DB_CONFIG_DAO = "dmdatabaseDbConfigDao";
public static final String DATABASE_ENTITY_DB_CONFIG_SERVICE = "dmdatabaseDbConfigService";
private static final String ENTITY_PACKAGE = "com.example.xyz.database.entity";
#Autowired
private org.springframework.core.env.Environment environment;
#Bean(name = DATABASE_ENTITY_DATA_SOURCE)
public DataSource databaseEntitydataSource() throws PropertyVetoException {
// mongodb properties
String driverClass = environment.getProperty("databaseEntity.mongodb.driverClassName");
String mongodbUrl = environment.getProperty("databaseEntity.mongodb.dmdatabaseDataSource.url");
String user = environment.getProperty("databaseEntity.mongodb.dmdatabaseDataSource.username");
String password = environment.getProperty("databaseEntity.mongodb.dmdatabaseDataSource.password");
Preconditions.checkArgument(StringUtils.isNotBlank(driverClass), "The property mongodb driverClass must not be null or blank");
Preconditions.checkArgument(StringUtils.isNotBlank(mongodbUrl), "The property mongodb mongodbUrl must not be null or blank");
Preconditions.checkArgument(StringUtils.isNotBlank(user), "The property mongodb user must not be null or blank");
Preconditions.checkArgument(StringUtils.isNotBlank(password), "The property mongodb password must not be null or blank");
dataSource.setDriverClass(driverClass);
dataSource.setmongodbUrl(mongodbUrl);
dataSource.setUser(user);
dataSource.setPassword(password);
return dataSource;
}
#Bean(name = DATABASE_ENTITY_SESSION_FACTORY)
public AnnotationSessionFactoryBean databaseEntitySessionFactory() throws PropertyVetoException {
AnnotationSessionFactoryBean annotationSessionFactoryBean = new AnnotationSessionFactoryBean();
annotationSessionFactoryBean.setDataSource(databaseEntitydataSource());
annotationSessionFactoryBean.setPackagesToScan(ENTITY_PACKAGE);
annotationSessionFactoryBean.setAnnotatedClasses(DBConfig.class);
annotationSessionFactoryBean.setHibernateProperties(databaseEntityHibernateProperties());
return annotationSessionFactoryBean;
}
#Bean(name = DATABASE_ENTITY_TRANSACTION_MANAGER)
public HibernateTransactionManager databaseEntityTransactionManager() throws PropertyVetoException {
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(databaseEntitySessionFactory().getObject());
return transactionManager;
}
}

Spring JPA Specify entity's table name on the repository interface

I have a scenario where I want to create multiple repositories for the same entity class.
The first and simplest scenario I want to save some of the instances of my class as rows in a different table than the primary table (which is designated on the entity itself).
other scenarios would be to create remote back ups hence the whole datasource would be different.
Does Spring allow things like that?
I'm not sure you'll want this, but here it is anyway... The best I could find using Spring Data Repositories is the following:
(1a) Manually define 2 repository beans to use 2 datasources:
#Bean
#Qualifier("db1")
public ModelJpaRepository modelJpaRepositoryDb1() {
JpaRepositoryFactoryBean<ModelJpaRepository, Model, String> myFactory = new JpaRepositoryFactoryBean<ModelJpaRepository, Model, String>();
myFactory.setRepositoryInterface(ModelJpaRepository.class);
myFactory.setEntityManager(entityManagerFactory1().createEntityManager());
myFactory.afterPropertiesSet();
return myFactory.getObject();
}
#Bean
#Qualifier("db2")
public ModelJpaRepository modelJpaRepositoryDb2() {
JpaRepositoryFactoryBean<ModelJpaRepository, Model, String> myFactory = new JpaRepositoryFactoryBean<ModelJpaRepository, Model, String>();
myFactory.setRepositoryInterface(ModelJpaRepository.class);
myFactory.setEntityManager(entityManagerFactory2().createEntityManager());
myFactory.afterPropertiesSet();
return myFactory.getObject();
}
(1b): Define the 2 datasources (referred to by the previous repository definitions):
#Bean(name = "dataSource1")
public DataSource dataSource1() {
BasicDataSource bds = new BasicDataSource();
bds.setDriverClassName(...);
bds.setUrl(...);
bds.setUsername(...);
bds.setPassword(...);
return bds;
}
#Bean(name = "dataSource2")
public DataSource dataSource2() {
BasicDataSource bds = new BasicDataSource();
bds.setDriverClassName(...);
bds.setUrl(...);
bds.setUsername(...);
bds.setPassword(...);
return bds;
}
(1c): Define 2 entityManagers - 1 per datasource (referred to by the previous repository definitions):
#Bean
public EntityManagerFactory entityManagerFactory1() {
LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
entityManagerFactory.setDataSource(dataSource1());
entityManagerFactory.setPersistenceUnitName("pu1");
entityManagerFactory.setJpaVendorAdapter(jpaVendorAdapter());
entityManagerFactory.setJpaProperties(jpaProperties());
entityManagerFactory.afterPropertiesSet();
return entityManagerFactory.getNativeEntityManagerFactory();
}
#Bean
public EntityManagerFactory entityManagerFactory2() {
LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
entityManagerFactory.setDataSource(dataSource2());
entityManagerFactory.setPersistenceUnitName("pu2");
entityManagerFactory.setJpaVendorAdapter(jpaVendorAdapter());
entityManagerFactory.setJpaProperties(jpaProperties());
entityManagerFactory.afterPropertiesSet();
return entityManagerFactory.getNativeEntityManagerFactory();
}
(2) Inject the 2 repositories and use them:
#Autowired
#Qualifier("db1")
private ModelJpaRepository modelJpaRepositoryDb1;
#Autowired
#Qualifier("db2")
private ModelJpaRepository modelJpaRepositoryDb2;
...
modelJpaRepositoryDb1.save(model);
modelJpaRepositoryDb2.save(model);
(3) Define the "OtherModel" and include the "Model" as embedded:
#Entity
#Table(name = "OTHER_TABLE")
public class OtherTable {
#Id
#Column(name = "ID", nullable = false)
private long id;
#Embedded
private Model model;
public OtherTable(Model model) {
this.model = model;
this.id = model.getId();
}
}
For info, This answer suggests using #Inheritance(strategy=InheritanceType.TABLE_PER_CLASS), to achieve define an additional model (inheritance vs composition).
(4) Define the 2 repositories for the OtherTable:
#Bean
#Qualifier("db1")
public OtherTableJpaRepository otherTableJpaRepositoryDb1() {
JpaRepositoryFactoryBean<OtherTableJpaRepository, OtherTable, String> myFactory = new JpaRepositoryFactoryBean<OtherTableJpaRepository, OtherTable, String>();
myFactory.setRepositoryInterface(OtherTableJpaRepository.class);
myFactory.setEntityManager(entityManagerFactory1().createEntityManager());
myFactory.afterPropertiesSet();
return myFactory.getObject();
}
#Bean
#Qualifier("db2")
public OtherTableJpaRepository otherTableJpaRepositoryDb2() {
JpaRepositoryFactoryBean<OtherTableJpaRepository, OtherTable, String> myFactory = new JpaRepositoryFactoryBean<OtherTableJpaRepository, OtherTable, String>();
myFactory.setRepositoryInterface(OtherTableJpaRepository.class);
myFactory.setEntityManager(entityManagerFactory2().createEntityManager());
myFactory.afterPropertiesSet();
return myFactory.getObject();
}
(5) Inject and use them all:
#Autowired
#Qualifier("db1")
private ModelJpaRepository modelJpaRepositoryDb1;
#Autowired
#Qualifier("db2")
private ModelJpaRepository modelJpaRepositoryDb2;
#Autowired
#Qualifier("db1")
private OtherTableJpaRepository otherTableJpaRepositoryDb1;
#Autowired
#Qualifier("db2")
private OtherTableJpaRepository otherTableJpaRepositoryDb2;
// ...
modelJpaRepositoryDb1.save(model);
otherTableJpaRepositoryDb1.save(new OtherTable(model));
modelJpaRepositoryDb2.save(model);
otherTableJpaRepositoryDb2.save(new OtherTable(model));

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