I can not Inject Spring Beans into Test using TestNG launcher (Multithreading) - java

#TransactionConfiguration
#Transactional
#ContextConfiguration(classes=AnnotationConfigContextLoaderUtils.class)
#WebAppConfiguration
#RunWith(SpringJUnit4ClassRunner.class)
public class AnyTest extends TestMachine {
#Inject
private AccountDao accDao; //ALLWAYS NULL
I run the test with:
TestNG testNG = new TestNG();
AppConfig.java
#Bean
public SessionScope sessionScope(){
return new SessionScope();
}
#Bean
public static PropertySourcesPlaceholderConfigurer propertyPlaceHolderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
#Bean
public JdbcTemplate jdbcTemplate() throws ConfigurationException {
return new JdbcTemplate(dataSource());
}
#Bean
public DataSource dataSource() throws ConfigurationException {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
//DB INITIALIZE
}
#Bean(name = "sessionFactory")
public LocalSessionFactoryBean sessionFactory() throws ConfigurationException {
LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
sessionFactoryBean.setDataSource(dataSource());
sessionFactoryBean.setPackagesToScan("package.model");
sessionFactoryBean.setHibernateProperties(hibProperties());
return sessionFactoryBean;
}
#Bean
public HibernateTransactionManager transactionManager() throws ConfigurationException {
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(sessionFactory().getObject());
return transactionManager;
}
private Properties hibProperties() {
Properties properties = new Properties();
properties.put("hibernate.hbm2ddl.auto", hibernateAuto);
properties.put("hibernate.dialect", hibernateDialect);
properties.put("hibernate.show_sql", showSQL);
return properties;
}
SpringMVCInitializer.java
public class SpringMVCInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] {AppConfig.class, SpringMVCConfiguration.class, SimpleCORSFilter.class};
}
#Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
Maven dependency versions:
<spring-version>4.0.3.RELEASE</spring-version>
<spring-test>4.0.3.RELEASE</spring-test>
<testNG-Version>6.9.4</testNG-Version>
<hibernate.version>4.1.5.Final</hibernate.version>
<hibernate-validator>4.2.0.Final</hibernate-validator>
<mysql.connector.version>5.1.32</mysql.connector.version>
<dbcp.version>1.4</dbcp.version>
Why I can't inject any bean to a test?
Note: I used #Autowired and it did not work too.
One sugestion is inject the session in the main method I used to run the test.
Is any way to make this?

I resolved this problem creating a Static Class and injecting the dependencies into this class in a controller.
Controller:
#Controller
public class InitController {
#Inject
public InitController(TestDao testDao, InsynctivePropertyDao propertyDao, ServletContext servletContext, AccountDao accDao, CrossBrowserAccountDao crossDao, CreatePersonFormDao createPersonFormDao, TestSuiteDao testSuiteDao) {
HibernateUtil.init(testDao, propertyDao, servletContext, accDao, crossDao, createPersonFormDao, testSuiteDao);
}
}
HibernateUtil.java
public class HibernateUtil {
public static CrossBrowserAccountDao crossDao;
public static TestDao testDao;
public static synchronized void init(TestDao testDao, InsynctivePropertyDao propertyDao, ServletContext servletContext, AccountDao accDao, CrossBrowserAccountDao crossDao, CreatePersonFormDao createPersonFormDao, TestSuiteDao testSuiteDao){
HibernateUtil.crossDao = crossDao;
HibernateUtil.testDao = testDao;
}
}

Related

NullPointerException getting hibernate session

I am trying to integrate Hibernate 5.2.12 into my Spring application but am getting a nullPointerException when get a session.
Here is the Hibernate configuration
#Configuration
#EnableTransactionManagement
public class HibernateConfig {
#Bean
public LocalSessionFactoryBean sessionFactory() {
System.out.println("Session factory called!");
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(
"com.app.persistence.model");
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
#Bean
public DataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/appDatabase?useSSL=false");
dataSource.setUsername("root");
dataSource.setPassword("password");
return dataSource;
}
#Bean
public PlatformTransactionManager hibernateTransactionManager() {
HibernateTransactionManager transactionManager
= new HibernateTransactionManager();
transactionManager.setSessionFactory(sessionFactory().getObject());
return transactionManager;
}
private final Properties hibernateProperties() {
Properties hibernateProperties = new Properties();
hibernateProperties.setProperty(
"hibernate.hbm2ddl.auto", "");
hibernateProperties.setProperty(
"hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
return hibernateProperties;
}
}
Here is the my util class where sessionFactory is #AutoWired
public class AppHibernateUtil {
private static final AppHibernateUtil instance = new AppHibernateUtil();
#Autowired
private SessionFactory sessionFactory;
public static Session getSession() {
return getInstance().sessionFactory.openSession();
}
private static AppHibernateUtil getInstance() {
return instance;
}
}
Here's my attempted usage of a session
public static String getRoles() {
System.out.println("Custom: getRoles() called");
List<RoleEntity> roles = new ArrayList<>();
try(Session session = AppHibernateUtil.getSession()){
roles = session.createQuery("from RoleEntity").list();
}
return gson.toJson(roles.size());
}
public static void main(String args[]) {
System.out.println(getRoles());
}
The null exception is thrown here
return getInstance().sessionFactory.openSession();
This line never gets outputted at the console
System.out.println("Session factory called!");
If I ignore the AppHibernateUtil class by creating a test class which injects (or not) the sessionFactory. I get the same NPE
#Component
public class TestController {
private static Gson gson = new Gson();
#Autowired
private static SessionFactory sessionFactory;
public static String getRoles() {
System.out.println("Custom: getRoles() called");
List<RoleEntity> roles = new ArrayList<>();
try(Session session = sessionFactory.getCurrentSession()){
roles = session.createQuery("from RoleEntity").list();
}
return gson.toJson(roles.size());
}
public static void main(String args[]) {
System.out.println(getRoles());
}
}
Problem is not in your hibernate configuration, but in your dependency injection.
You are creating manually singleton of AppHibernateUtil (you are calling new AppHibernateUtil()), let Spring do its job and annotate AppHibernateUtil with #Component (default scope of component is Singleton), then inject it into you class, where is your session needed.
My guess is that the NPE is being thrown because the sessionFactory in the getSession() method is null.
This means that Spring is not injecting an instance of SessionFactory.
That may be because you've chosen to implemented the AppHibernateUtil as a singleton. I won't disgress into a discussion about that, except that's it's relevant to point out that Spring is based on dependency injection and using singletons goes against that approach.
If you want to keep using a singleton, you may have success with additional annotations on the AppHibernateUtil class:
#Configuration
#ComponentScan("com.your.package.HibernateConfig")
public class AppHibernateUtil {
...
}
However, as described in the docs, it would probably be best to refactor the AppHibernateUtil class so that it was not a singleton:
#Configuration
public class AppHibernateUtil {
private final AppConfig appConfig;
public AppHibernateUtil(AppConfig appConfig) {
this.appConfig = appConfig;
}
}

TaskConfigurer does not considering schema name for datasource

I have 2 data source. For one data source, I want to use custom schema name. For this reason, I am setting my data source url like
spring.datasource.url=jdbc:postgresql://192.168.33.10/analytics?currentSchema=bahmni_mart_scdf.
But it's creating all the tables in public schema, instead of bahmni_mart_scdf schema.
I already override TaskRepositoryInitializer bean and implements TaskConfigurer.
Here are my implementations
DatabaseConfiguration.class
#Configuration
public class DatabaseConfiguration {
#Bean(name = "martDb")
#ConfigurationProperties(prefix = "spring.ds_mart")
public DataSource martDataSource() {
return DataSourceBuilder.create().build();
}
#Bean(name = "martJdbcTemplate")
public JdbcTemplate martJdbcTemplate(#Qualifier("martDb") DataSource dsMart) {
return new JdbcTemplate(dsMart);
}
#Bean(name = "scdfDb")
#ConfigurationProperties(prefix = "spring.datasource")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
#Bean(name = "scdfJdbcTemplate")
public JdbcTemplate scdfJdbcTemplate(#Qualifier("scdfDb") DataSource scdfDb) {
return new JdbcTemplate(scdfDb);
}
}
DataloadTaskConfigurer.class
#Component
public class DataloadTaskConfigurer implements TaskConfigurer {
private DataSource dataSource;
private TaskRepository taskRepository;
private TaskExplorer taskExplorer;
private PlatformTransactionManager transactionManager;
#Autowired
public DataloadTaskConfigurer(#Qualifier("scdfJdbcTemplate") JdbcTemplate jdbcTemplate) {
this.dataSource = jdbcTemplate.getDataSource();
TaskExecutionDaoFactoryBean taskExecutionDaoFactoryBean = new TaskExecutionDaoFactoryBean(dataSource);
this.taskRepository = new SimpleTaskRepository(taskExecutionDaoFactoryBean);
this.taskExplorer = new SimpleTaskExplorer(taskExecutionDaoFactoryBean);
}
#Override
public TaskRepository getTaskRepository() {
return this.taskRepository;
}
#Override
public PlatformTransactionManager getTransactionManager() {
if (this.transactionManager == null) {
this.transactionManager = new DataSourceTransactionManager(this.dataSource);
}
return this.transactionManager;
}
#Override
public TaskExplorer getTaskExplorer() {
return this.taskExplorer;
}
public DataSource getTaskDataSource() {
return this.dataSource;
}
}
TaskConfiguration.class
#Configuration
public class TaskConfiguration {
#Bean
public TaskRepositoryInitializer taskRepositoryInitializerInDataMart(#Qualifier("scdfJdbcTemplate") JdbcTemplate jdbcTemplate) throws Exception {
TaskRepositoryInitializer taskRepositoryInitializer = new TaskRepositoryInitializer();
taskRepositoryInitializer.setDataSource(jdbcTemplate.getDataSource());
taskRepositoryInitializer.afterPropertiesSet();
return taskRepositoryInitializer;
}
}
application.properties
spring.datasource.url=jdbc:postgresql://192.168.33.10/analytics?currentSchema=bahmni_mart_scdf
spring.datasource.username=analytics
spring.datasource.password=""
spring.datasource.driver-class-name=org.postgresql.Driver
spring.ds_mart.url=jdbc:postgresql://192.168.33.10/analytics
spring.ds_mart.username=analytics
spring.ds_mart.password=""
spring.ds_mart.driver-class-name=org.postgresql.Driver
You'll need to not override the TaskRepositoryInitializer, but turn it off all together via spring.cloud.task.initialize.enable=false. From there, using Spring Boot, you'll want to pass in the schema for each datasource:
spring.datasource.schema=schema1.sql
spring.ds_mart.schema=schema2.sql
The problem was with the postgresql driver version. Once I update to latest version (42.2.2) everything working fine as expected

Transaction doesn't work for Spring-Boot + Mybatis

My application using Spring Boot + MyBatis, When I using #Transactional annotation, it doesn't rollback when throw exception.
My MybatisConfiguration.java is:
#Configuration
#EnableTransactionManagement
#MapperScan("com.mode.dao")
public class MybatisConfiguration implements EnvironmentAware {
private RelaxedPropertyResolver properties;
#Override
public void setEnvironment(Environment env) {
this.properties = new RelaxedPropertyResolver(env, "mode.jdbc.");
}
#Bean(name = "datasource", destroyMethod = "close", initMethod = "init")
public DataSource dataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(properties.getProperty("driverClassName"));
dataSource.setUrl(properties.getProperty("url"));
dataSource.setUsername(properties.getProperty("username"));
dataSource.setPassword(properties.getProperty("password"));
dataSource.setMaxActive(properties.getProperty("maxActive", Integer.class, 1));
dataSource.setInitialSize(properties.getProperty("initialSize", Integer.class, 1));
return dataSource;
}
#Bean
public DataSourceTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
#Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
return sessionFactory.getObject();
}
}
and the service codes snapshot is:
#Override
#Transactional(propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
public Map<String, String> productImport(Product product) throws Exception {
.....
}
Application.java is:
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
}
build.gradle is:
// Spring Boot MVC
compile("org.springframework.boot:spring-boot-starter-web")
// Spring Boot jdbc
compile("org.springframework.boot:spring-boot-starter-jdbc")
// Mybatis
compile("org.mybatis:mybatis:${mybatisVersion}")
compile("org.mybatis:mybatis-spring:${mybatisSpringVersion}")
I used spring + mybatis before and the #Transactional annotation worked well, but when I changed to spring-boot it doesn't work...
Any help or ideas would be greatly appreciated, Thanks in advance!

Unable to autowire service in extended java class, throwing NullPointerException

I'm trying to Autowire service inside java class which is extended from TimerTask. This Returning null value while trying to return service in java class. This is the class in which I'm trying to Autowire service:
#Component
public class Task extends TimerTask
{
#Autowired
FileDetailsService fileDetailsService;
int count = 1;
#Override
public void run()
{
fileDetailsService.updateProcessingStatus(fileAudit);
}
Configuration classes: There is no web.xml.....I have configured in java using spring 4
//DataConfig.java
#Configuration
#MapperScan("com.fileC.mapper")
public class DataConfig {
#Bean
public DataSource dataSource() {
SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
dataSource.setDriverClass(oracle.jdbc.driver.OracleDriver.class);
dataSource.setUsername("username");
dataSource.setUrl("jdbc***thin**sample **url");
dataSource.setPassword("****");
return dataSource;
}
#Bean
public DataSourceTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
#Bean
public SqlSessionFactoryBean sqlSessionFactory() throws Exception {
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setTypeAliasesPackage("com.fileC.model");
return sessionFactory;
}
//ApplConfig.java
#Configuration
#ComponentScan(basePackages="com.filec")
public class ApplConfig {
#Bean
public CommonsMultipartResolver multipartResolver(){
CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver();
commonsMultipartResolver.setDefaultEncoding("utf-8");
commonsMultipartResolver.setMaxUploadSize(50000000);
return commonsMultipartResolver;
}
}
I'm using Spring4, java1.8, ibatis, SQL database.
Here is the service class,
#Service("fileDetailsService")
#Transactional
public class FileDetailsServiceImpl implements FileDetailsService{
private static Logger logger = LoggerFactory.getLogger(FileDetailsServiceImpl.class);
#Autowired
FileDetailsMapper fileDetailsMapper;
#Override
public void insertFileInfo(Details details){
fileDetailsMapper.insertDetails(details);
}
Here is the exception details,
fileAuditMapper>>>>null
Exception in thread "Timer-9" java.lang.NullPointerException at com.filecompare.service.Task.run(Task.java:117)
at java.util.TimerThread.mainLoop(Timer.java:555)
at java.util.TimerThread.run(Timer.java:505)
Please, let me know if I need to add something in config.

(Spring MVC + Hibernate 4 + Test 4) autowired DAO return NULL

Maven Dependencies
<!-- SPRING MVC -->
<spring-version>4.0.3.RELEASE</spring-version>
<spring-test-version>4.2.1.RELEASE</spring-test-version>
<!-- TESTS -->
<junit-Version>4.11</junit-Version>
<!-- DATA BASE -->
<hibernate.version>4.1.5.Final</hibernate.version>
<hibernate-validator>4.2.0.Final</hibernate-validator>
<mysql.connector.version>5.1.32</mysql.connector.version>
AccountDao.java
#Repository
#Transactional
public class AccountDao {
private final SessionFactory sessionFactory;
#Inject
public AccountDao(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
[...]
}
Test
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {SpringMVCInitializer.class}, loader=AnnotationConfigContextLoader.class)
public class LoadingTests extends TestMachine {
#Autowired
private AccountDao accountDao;
AppConfig.java
#Configuration
#PropertySource("classpath:application.properties")
#ComponentScan(basePackages = "company")
#EnableTransactionManagement
public class AppConfig {
#Bean
public AccountDao accountDao() {
return new AccountDao();
}
#Bean
public PropertySourcesPlaceholderConfigurer propertyPlaceHolderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
#Bean
public JdbcTemplate jdbcTemplate() {
return new JdbcTemplate(dataSource());
}
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
/*LOCAL*/
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/compamny");
dataSource.setUsername("root");
dataSource.setPassword("");
return dataSource;
}
#Bean(name = "sessionFactory")
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
sessionFactoryBean.setDataSource(dataSource());
sessionFactoryBean.setPackagesToScan("insynctive.model");
sessionFactoryBean.setHibernateProperties(hibProperties());
return sessionFactoryBean;
}
#Bean
public HibernateTransactionManager transactionManager() {
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(sessionFactory().getObject());
return transactionManager;
}
private Properties hibProperties() {
Properties properties = new Properties();
properties.put(Environment.HBM2DDL_AUTO, "create");
properties.put(Environment.DIALECT, "org.hibernate.dialect.MySQLDialect");
properties.put(Environment.SHOW_SQL, true);
return properties;
}
}
SpringMVCConfiguration.java
#Configuration
#EnableWebMvc
#ComponentScan(basePackages="company.controller")
public class SpringMVCConfiguration extends WebMvcConfigurerAdapter {
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolverJSP = new InternalResourceViewResolver();
viewResolverJSP.setOrder(1);
viewResolverJSP.setViewClass(JstlView.class);
viewResolverJSP.setPrefix("views/jsp/");
viewResolverJSP.setSuffix(".jsp");
return viewResolverJSP;
}
}
SpringMVCInitializer.java
public class SpringMVCInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] {AppConfig.class, SpringMVCConfiguration.class};
}
#Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
My autowired of AccountDao is returning null Why? but in my web application everything works good.
I Try lot of things like:
Create a new sessionFactory but doesn't work.
Used: classes ={AppConfig.class,SpringMVCConfig.class}.
Used: #ContextConfiguration(initializers = {SpringMVCInitializer.class}, loader=AnnotationConfigContextLoader.class) throw Type mismatch: cannot convert from Class to Class>
Used: #SpringApplicationConfiguration(classes = {SpringMVCInitializer.class})
I think you need to set initializers instead of classes on your LoadingTests class.
#ContextConfiguration(initializers = {SpringMVCInitializer.class}, loader=AnnotationConfigContextLoader.class)
Also please consider using constructor injection on your DAO.
Since you have #Repository you should include them with
#EnableJpaRepositories(basePackages="yourrepositories") at your config class
try adding
#WebAppConfiguration
before you test class.
The mere presence of #WebAppConfiguration on a test class ensures that a
WebApplicationContext will be loaded for the test using a default for
the path to the root of the web application.
I resolved this making a HibernateUtils to create a sessionFactory.

Categories