Spring - trouble with injecting validator bean - java

i couldn't find solution for my problem anywhere.
I'm trying to make validation working in spring web flow form. I need to
set validator in configuration, however it's located in another config file
and it seems spring can't find proper bean. How can I achieve successful injection here?
As far as I know, Autowiring should inject bean into validator reference.
Maybe it has something to do with order of loading configuration classes?
WebConfig.java:
#Configuration
#Import(godziszewski.patryk.ElectronicsStore.config.FlowConfiguration.class)
#EnableWebMvc
#ComponentScan(basePackages = "godziszewski.patryk")
public class WebConfig extends WebMvcConfigurerAdapter {
....
#Bean
public LocalValidatorFactoryBean validator()
{
LocalValidatorFactoryBean lv = new LocalValidatorFactoryBean();
lv.setValidationMessageSource(messageSource());
return lv;
}
}
FlowConfiguration.java:
#Configuration
public class FlowConfiguration extends AbstractFlowConfiguration {
#Autowired
Validator validator;
....
#Bean
public FlowBuilderServices flowBuilderServices()
{
FlowBuilderServices fbs = new FlowBuilderServices();
fbs.setValidator(validator);
return fbs;
}
}
The error i'm getting:
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'flowConfiguration':
Unsatisfied dependency expressed through field 'validator':
No qualifying bean of type [org.springframework.validation.Validator] found for dependency [org.springframework.validation.Validator]:
expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)};
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type [org.springframework.validation.Validator] found for dependency [org.springframework.validation.Validator]:
expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
Im using spring 4.3.2.RELEASE
However, when I delete Validator dependency from FlowAdapter.class I get error :
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'flowBuilderServices' defined in class path resource [godziszewski/patryk/ElectronicsStore/config/FlowConfiguration.class]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: The ViewFactoryCreator is required
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1578)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:381)
at godziszewski.patryk.ElectronicsStore.config.FlowConfiguration$$EnhancerBySpringCGLIB$$b65e14d6.flowBuilderServices(<generated>)
at godziszewski.patryk.ElectronicsStore.config.FlowConfiguration.flowRegistry(FlowConfiguration.java:25)
at godziszewski.patryk.ElectronicsStore.config.FlowConfiguration$$EnhancerBySpringCGLIB$$b65e14d6.CGLIB$flowRegistry$3(<generated>)
at godziszewski.patryk.ElectronicsStore.config.FlowConfiguration$$EnhancerBySpringCGLIB$$b65e14d6$$FastClassBySpringCGLIB$$e5741e7e.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:356)
at godziszewski.patryk.ElectronicsStore.config.FlowConfiguration$$EnhancerBySpringCGLIB$$b65e14d6.flowRegistry(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162)
... 24 more
Caused by: java.lang.IllegalArgumentException: The ViewFactoryCreator is required
Full FlowConfiguration class code, maybe I'm doing something wrong?
package godziszewski.patryk.ElectronicsStore.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.Validator;
import org.springframework.webflow.config.AbstractFlowConfiguration;
import org.springframework.webflow.definition.registry.FlowDefinitionRegistry;
import org.springframework.webflow.engine.builder.support.FlowBuilderServices;
import org.springframework.webflow.executor.FlowExecutor;
import org.springframework.webflow.mvc.servlet.FlowHandlerAdapter;
import org.springframework.webflow.mvc.servlet.FlowHandlerMapping;
#Configuration
public class FlowConfiguration extends AbstractFlowConfiguration {
#Bean
public FlowDefinitionRegistry flowRegistry() {
return getFlowDefinitionRegistryBuilder()
.setBasePath("/WEB-INF/flows")
.setFlowBuilderServices(flowBuilderServices())
.addFlowLocationPattern("/**/*-flow.xml")
.build();
}
#Bean
public FlowExecutor flowExecutor() {
return getFlowExecutorBuilder(flowRegistry()).build();
}
#Bean
public FlowHandlerMapping flowHandlerMapping()
{
System.out.println("flowconfig");
FlowHandlerMapping fh = new FlowHandlerMapping();
fh.setFlowRegistry(flowRegistry());
return fh;
}
#Bean
public FlowHandlerAdapter flowHandlerAdapter()
{
FlowHandlerAdapter fh = new FlowHandlerAdapter();
fh.setFlowExecutor(flowExecutor());
return fh;
}
#Bean
public FlowBuilderServices flowBuilderServices()
{
FlowBuilderServices fbs = new FlowBuilderServices();
//fbs.setValidator(validator);
return fbs;
}
}
If i delete .setFlowBuilderServices(flowBuilderServices()) method, everything works fine
EDIT: I managed to get this working by deleting #Configuration annotation form flow config class, now it looks like this:
//#Configuration
public class FlowConfiguration extends AbstractFlowConfiguration {
#Autowired
Validator validator;
...
#Bean
public FlowBuilderServices flowBuilderServices()
{
System.out.println(validator.toString());
FlowBuilderServices fbs = new FlowBuilderServices();
fbs.setValidator(validator);
return fbs;
}
And now I can use injected LocalValidatorBean in this class.

I interpret that eventually you need a FlowBuilderServices which has a reference to Validator bean.
This can be achieved by using the Autowired tag inside FlowBuilderServices
public class FlowBuilderServices{
#Autowired
Validator validator
...
}
And then in FlowConfiguration you just need to define the bean
#Bean
public class FlowBuilderServices flowBuilderServices()
{
FlowBuilderServices fbs = new FlowBuilderServices();
return fbs;
}

Related

Spring AOP: UnsatisfiedDependencyException error with configuration with annotation

I'm having a trouble while configuring Spring AOP.
I created an aspect class which is below:
#Slf4j
#Aspect
#RequiredArgsConstructor
#Component
public class LoggingAspect {
private static final Logger logger = CommonLogger.getLogger(LoggingAspect.class);
private final ObjectMapper mapper;
private final JobExecutionService jobExecutionService;
}
Then I added a configuration file:
#Configuration
#EnableAspectJAutoProxy(proxyTargetClass = true)
#RequiredArgsConstructor
public class AspectConfiguration {
private final ObjectMapper objectMapper;
private final JobExecutionService jobExecutionService;
#Bean
public LoggingAspect loggingAspect() {
return new LoggingAspect(objectMapper, jobExecutionService);
}
}
But when I started the application, I am getting below errors:
Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.context.support.ClassPathXmlApplicationContext]: Constructor threw exception; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'aspectConfiguration' defined in URL: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.fasterxml.jackson.databind.ObjectMapper' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
I have added aspectjrt and aspectjweaver dependencies to pom.xml.
Spring version is 4.3.6
I couldn't figure out where the problem is. Any help would be appreciated.
Add class:
#Configuration
public class BeanConfig {
#Bean
public ObjectMapper objectMapper() {
return new ObjectMapper();
}
}

Getting Exception while creating beans using #Bean Spring annotation

I was trying to understand difference between #component and #Bean in Spring framework, and referred to this SO question.
Based on the answer, I got a fair understanding, and tried to reinforce the concept by implementing a simple example (to check whether I really understood the concept).
The below is the code which I wrote. I wanted to see #Bean for "third party" libs (so that it can be instantiated using #Bean annotation)
package com.example.thirdparty.code;
public class ThirdPartyUtil {
public ThirdPartyUtil() {
}
public void print(String str) {
System.out.println("String passed is --> " + str);
}
}
In above, I tried to simulate a "third party lib/class - NON spring" which isn't a spring based (and so there won't be any #component in that class.
Now, below is the main application which I created:
package com.example.spring;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import com.example.thirdparty.code.ThirdPartyUtil;
#Configuration
#ComponentScan(basePackages = { "com.example.spring" })
#Component
public class SpringBasedMainApp {
#Autowired
private ApplicationContext ctx;
#Autowired
private static ThirdPartyUtil thirdPartyUtil;
#Bean
public ThirdPartyUtil beanThirdPartyUtil() {
try {
Class c = getClass().getClassLoader().loadClass("com.example.thirdparty.code.ThirdPartyUtil");
return (ThirdPartyUtil) ctx.getBean(c);
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("Exception");
}
}
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringBasedMainApp.class);
System.out.println("thirdPartyUtil is " + thirdPartyUtil);
}
}
I was hoping that using #Bean annotation, it would create ThirdPartyUtil as Spring bean, and then inject using #Autowired into field thirdPartyUtil.
However, when I run this program, I got altogether a surprising exception, listed below:
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'beanThirdPartyUtil' defined in com.example.spring.SpringBasedMainApp: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.example.thirdparty.code.ThirdPartyUtil]: Factory method 'beanThirdPartyUtil' threw exception; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'beanThirdPartyUtil': Requested bean is currently in creation: Is there an unresolvable circular reference?
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:627)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:456)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1288)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1127)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:538)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:846)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:863)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:546)
at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:88)
at com.example.spring.SpringBasedMainApp.main(SpringBasedMainApp.java:41)
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.example.thirdparty.code.ThirdPartyUtil]: Factory method 'beanThirdPartyUtil' threw exception; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'beanThirdPartyUtil': Requested bean is currently in creation: Is there an unresolvable circular reference?
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:622)
... 14 more
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'beanThirdPartyUtil': Requested bean is currently in creation: Is there an unresolvable circular reference?
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.beforeSingletonCreation(DefaultSingletonBeanRegistry.java:339)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:215)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:224)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1112)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveBean(DefaultListableBeanFactory.java:407)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:341)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:335)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1101)
at com.example.spring.SpringBasedMainApp.beanThirdPartyUtil(SpringBasedMainApp.java:33)
at com.example.spring.SpringBasedMainApp$$EnhancerBySpringCGLIB$$d93c67f4.CGLIB$beanThirdPartyUtil$0(<generated>)
at com.example.spring.SpringBasedMainApp$$EnhancerBySpringCGLIB$$d93c67f4$$FastClassBySpringCGLIB$$9349d69b.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:363)
at com.example.spring.SpringBasedMainApp$$EnhancerBySpringCGLIB$$d93c67f4.beanThirdPartyUtil(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
... 15 more
I didn't understand why it is giving this exception. I am creating an applicationContext using AnnotationConfigApplicationContext and passing the necessary details to it.
I expected it to work, however got the above exception (which I have seen maiden time).
Why has this exception been thrown, is my understanding not correct about #Bean?
The goal of the #Bean annotation is to annotate a method whose responsibility is to create an object, that will then be registered as a bean by Spring.
But inside your method, you ask Spring (using ctx.getBean()) to give you the bean that you're currently creating. So you get that exception.
Here's what your methd should look like:
#Bean
public ThirdPartyUtil beanThirdPartyUtil() {
return new ThirdPartyUtil();
}
To extend #JB Nizet answer, instantiate your third party class in spring constructor like below.
#Autowired
private static ThirdPartyUtil thirdPartyUtil;
#Autowired
public SpringBean() {
this.thirdPartyUtil = new ThirdPartyUtil();
}

Autowiring fails in Junit testing and spring #configuration

I have two #Configuration classes. I need a bean from one configuration class to another. I have autowired the configuration 1 into 2. All works fine. When executing the unit testing, am getting the below exception.
setUpContext(com.trafigura.titan.framework.services.messaging.loader.SpringLoadTest)
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.xxx.MessagingServicesConfig': Injection of autowired dependencies failed;
nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.xxx.EMSJMSConfig com.xxx.MessagingServicesConfig.emsJmsConfig;
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type[com.xxx.EMSJMSConfig] found for dependency:
expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
Is there anything I need to do additionally to make this working?
Below is the setup for testing.
#Configuration
#Import({MessagingServicesConfig.class,...,EMSJMSConfig.class
})
public class MessagingConfig {}
#Profile("EMS-MESSAGING")
#Configuration
public class EMSJMSConfig {
#Bean
public javax.jms.ConnectionFactory jmsSubscriberConnectionFactory() throws JMSException {
SingleConnectionFactory singleConnectionFactory = new SingleConnectionFactory(tibjmsConnectionFactory());
return singleConnectionFactory;
}
}
#Configuration
public class MessagingServicesConfig {
#Autowired
private EMSJMSConfig emsJmsConfig;
#Bean(destroyMethod = "shutdown")
public MessagingService messagingService() throws JMSException {
...
ConnectionFactory cf=emsJmsConfig.jmsSubscriberConnectionFactory(); // Getting NPE at this line.
}
}
and finally the test class,
public class MessagingServicesConfigTest {
private MessagingServicesConfig config;
private EMSJMSConfig emsJmsConfig;
#BeforeMethod
public void setUp() throws Exception {
config = new MessagingServicesConfig();
... //what needs to be done here to have the EMSJMSConfig
}
#Test
public void testBuildsCorrectService() throws JMSException {
MessagingService service = config.messagingService();
...
}
}
By calling new you're creating object yourself, Spring doesn't know anything about it.
Moreover, you should have a test configuration which will be aware of your beans.
Use an appropriate Runner to load SpringContext.
#ContextConfiguration(classes = TestConfig.class)
#RunWith(SpringRunner.class)
class Tests {
#Autowired // if needed
private MessagingServicesConfig config;
}
While in TestConfig you can create beans or import configuration from the Application:
#Configuration
#Import({MessagingServicesConfig.class})
public class TestConfig {}
#Configuration
#Import({EMSJMSConfig.class})
public class MessagingServicesConfig {}
Or you can refer to your config classes directly:
#ContextConfiguration(classes = {MessagingServicesConfig.class, EMSJMSConfig.class})

No qualifying bean of type UserRepository found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency

Hey I have problem with extending repository from Spring data.
I have controller that talks with service layer:
#RestController
public class UserController {
#Autowired
public UserService userService;
#RequestMapping(value = ServerRouting.UserService.getList, method = RequestMethod.GET)
public #ResponseBody Iterable<UserEntity> getList() {
return userService.getList();
}
}
here is service layer:
#Service
public class UserService {
#Autowired
public UserRepository repository;
#Transactional
public Iterable<UserEntity> getList() {
return repository.findAll();
}
}
service layer talks to repository/dao layer. Repository is an interface that extends org.springframework.data.repository;CrudRepository from spring data:
#Repository
public interface UserRepository extends CrudRepository<UserEntity, Long> {}
In this crud repository are methods that I would like to use, f.e findAll()
But when I run this project on tomcat, I am getting an error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: public pl.korbeldaniel.cms.server.service.UserService pl.korbeldaniel.cms.server.controller.UserController.userService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: public pl.korbeldaniel.cms.server.dao.UserRepository pl.korbeldaniel.cms.server.service.UserService.repository; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [pl.korbeldaniel.cms.server.dao.UserRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
I think the problem is related with this: No qualifying bean of type [pl.korbeldaniel.cms.server.dao.UserRepository] found for dependency.
cause I do not have an repository implementation that could be injected, but for me it is the point of using spring-data: just to create simple interface, as in this example
Here is my persistence configuration:
package pl.korbeldaniel.cms.server.config;
import java.util.Properties;
import javax.annotation.Resource;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
#Configuration
#EnableJpaRepositories(basePackages = { "pl.korbeldaniel.cms.server;" })
#PropertySource("classpath:application.properties")
#EnableTransactionManagement
class PersistenceContext {
#Resource
private Environment env;
#Bean(destroyMethod = "close")
DataSource dataSource(Environment env) {
HikariConfig dataSourceConfig = new HikariConfig();
dataSourceConfig.setDriverClassName(env.getRequiredProperty("db.driver"));
dataSourceConfig.setJdbcUrl(env.getRequiredProperty("db.url"));
dataSourceConfig.setUsername(env.getRequiredProperty("db.username"));
dataSourceConfig.setPassword(env.getRequiredProperty("db.password"));
return new HikariDataSource(dataSourceConfig);
}
#Bean
LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource, Environment env) {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSource);
entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
entityManagerFactoryBean.setPackagesToScan("pl.korbeldaniel.cms.server");
Properties jpaProperties = new Properties();
//Configures the used database dialect. This allows Hibernate to create SQL
//that is optimized for the used database.
jpaProperties.put("hibernate.dialect", env.getRequiredProperty("hibernate.dialect"));
//Specifies the action that is invoked to the database when the Hibernate
//SessionFactory is created or closed.
jpaProperties.put("hibernate.hbm2ddl.auto", env.getRequiredProperty("hibernate.hbm2ddl.auto"));
//Configures the naming strategy that is used when Hibernate creates
//new database objects and schema elements
jpaProperties.put("hibernate.ejb.naming_strategy", env.getRequiredProperty("hibernate.ejb.naming_strategy"));
//If the value of this property is true, Hibernate writes all SQL
//statements to the console.
jpaProperties.put("hibernate.show_sql", env.getRequiredProperty("hibernate.show_sql"));
//If the value of this property is true, Hibernate will format the SQL
//that is written to the console.
jpaProperties.put("hibernate.format_sql", env.getRequiredProperty("hibernate.format_sql"));
entityManagerFactoryBean.setJpaProperties(jpaProperties);
return entityManagerFactoryBean;
}
#Bean
JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory);
return transactionManager;
}
}
Please help.
#EnableJpaRepositories(basePackages = { "pl.korbeldaniel.cms.server;" })
remove the semicolon and clean and build your application,
#EnableJpaRepositories(basePackages = { "pl.korbeldaniel.cms.server"})
error says no Bean found at the given location pl.korbeldaniel.cms.server.dao.UserRepository
moving your beans to the above location will also work.

Unit testing a Spring Boot service class with(out) repository in JUnit

I am working on a spring boot based webservice with following structure:
Controller (REST) --> Services --> Repositories (as suggested in some tutorials).
My Database Connection (JPA/Hibernate/MySQL) is defined in a #Configuration class. (see below)
Now I'd like to write simple tests for methods in my Service classes, but I don't really understand how to load ApplicationContext into my test classes and how to mock the JPA / Repositories.
This is how far I came:
My service class
#Component
public class SessionService {
#Autowired
private SessionRepository sessionRepository;
public void MethodIWantToTest(int i){
};
[...]
}
My test class:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(loader = AnnotationConfigContextLoader.class)
public class SessionServiceTest {
#Configuration
static class ContextConfiguration {
#Bean
public SessionService sessionService() {
return new SessionService();
}
}
#Autowired
SessionService sessionService;
#Test
public void testMethod(){
[...]
}
}
But I get following exception:
Caused by: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'sessionService': Injection of autowired
dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException: Could not
autowire field: private com.myApp.SessionRepository
com.myApp.SessionService.sessionRepository; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type [com.myApp.SessionRepository] found for
dependency: expected at least 1 bean which qualifies as autowire
candidate for this dependency. Dependency annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true)}
For completeness: here's my #Configuration for jpa:
#Configuration
#EnableJpaRepositories(basePackages={"com.myApp.repositories"})
#EnableTransactionManagement
public class JpaConfig {
#Bean
public ComboPooledDataSource dataSource() throws PropertyVetoException, IOException {
...
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource, JpaVendorAdapter jpaVendorAdapter) {
...
}
#Bean
public JpaVendorAdapter jpaVendorAdapter() {
...
}
#Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
...
}
#Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){
...
}
}
use #SpringBootTest and #RunWith(SpringRunner.class) to load the context
#RunWith(SpringRunner.class)
#SpringBootTest
class Demo{
#Test
void contextLoad(){}
}
In your test Spring will use configuration only from inner ContextConfiguration class. This class describes your context. In this context you created only service bean and no repository. So the only bean that will be created is SessionService. You should add description of SessionRepository in inner ContextConfiguration. Your JpaConfig class will not be used in test class(you don't specify this), only in application.

Categories