Spring Context Initialization fails - java

I'm pretty much stucked and I hope you guys can help me out. Somehow I can't manage to get my spring context initialized.
I have these nice Bean Configuration classes:
#Configuration
public class CoreConfig {
#Bean
public TeamService createService(TeamPersistenceService teamPersistenceService) {
return new TeamEventHandler(teamPersistenceService);
}
}
And this one:
#Configuration
#EnableJpaRepositories(basePackages = "de.ktv.persistence.repository", //
includeFilters = #ComponentScan.Filter(value = { TeamsRepository.class }, type = FilterType.ASSIGNABLE_TYPE))
#EnableTransactionManagement
public class PersistenceConfig {
#Bean
public TeamPersistenceService createService(TeamsRepository repository) {
return new TeamPersistenceEventHandler(repository);
}
}
And in this test I want to use them:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = { CoreConfig.class, PersistenceConfig.class })
public class CoreIntegrationTest {
#Autowired
TeamService teamService;
#Test
public void addNewTeamToTheSystem() {
//some test
}
The PersistenceConfig.class I am using in a different test and it works fine. But somehow here combined with CoreConfig.class it fails to initialize.
That is the error I get:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [de.ktv.core.services.TeamService] 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 would really appreciate any help/hint.Thanks!

SpringContext cannot bind the #autowired if you don't indicate the same name. By default, the bean name will be the same as the method name, in this case, he is different, 2 options : change the method name or add attribut name !
Option 1
#Bean(name = "teamService")
public TeamService createService(TeamsRepository repository) {
return new TeamPersistenceEventHandler(repository);
}
Option 2
#Bean
public TeamService teamService(TeamsRepository repository) {
return new TeamPersistenceEventHandler(repository);
}
Enjoy \o/

#Configuration
public class CoreConfig {
#Autowired
private TeamPersistenceService teamPersistenceService;
#Bean
public TeamService teamService() {
return new TeamEventHandler(teamPersistenceService);
}
}
And this one:
#Configuration
#EnableJpaRepositories(basePackages = "de.ktv.persistence.repository", //
includeFilters = #ComponentScan.Filter(value = { TeamsRepository.class }, type = FilterType.ASSIGNABLE_TYPE))
#EnableTransactionManagement
public class PersistenceConfig {
#Autowired
private TeamsRepository repository:
#Bean
public TeamPersistenceService teamPersistenceService() {
return new TeamPersistenceEventHandler(repository);
}
}
And in this test I want to use them:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = { CoreConfig.class, PersistenceConfig.class })
public class CoreIntegrationTest {
#Autowired
TeamService teamService;
#Test
public void addNewTeamToTheSystem() {
//some test
}

Related

ApplicationContext returns null in SpringBootTest run with SpringRunner.class

I have a problem of running my Test class. It returns "org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 't.c.i.s.se.Sfts' available: expected single matching bean but found 2: sftsImpl,sfts" this exception after I run it.
Here's my test class;
#RunWith(SpringRunner.class)
#SpringBootTest(classes = Sfta.class)
public class SftaTests {
#Autowired
ApplicationContext ac;
#Test
public void contextLoads() {
Sfts sfts= ac.getBean(Sfts.class);
assertTrue(Sfts instanceof SftsImpl);
}
}
And my other classes are like;
public interface Sfts {
public void process();
}
#Service
#Component
public class SftsImpl implements Sfts {
#Autowired
private GlobalConfig globalConfig;
#Autowired
private Ftr ftr;
private Fc fc;
#Async
#Scheduled(initialDelayString = "${s.f.t.m}", fixedRateString = "${s.f.t.m}")
public void process() {
int hod = DateTime.now().getHourOfDay();
if (hod != 6){
fc = new Fc(globalConfig, ftr);
fc.control();
}
}
}
Why I get the error after running the test application?
Try to remove #Component annotation from the SftsImpl bean.
#Service is enough to register a bean.
Also if you just want to test your bean - getting it from ApplicationContext maybe is not the best option.
Code example of a unit test without using ApplicationContext:
#RunWith(SpringRunner.class)
#SpringBootTest(classes = Sfta.class)
public class SftaTests {
#Autowired
Sfts sfts;
#Test
public void testAsync() {
sfts.process();
// do assertions here
}
}

How to test #Cacheable?

I am struggling with testing #Cacheable within a Spring Boot Integration Test. This is my second day learning how to do Integration Tests and all of the examples I have found use older versions. I also saw an example of assetEquals("some value", is()) but nothing with an import statement to know which dependency "is" belongs to. The test fails at the second
This is my integration test....
#RunWith(SpringRunner.class)
#DataJpaTest // used for other methods
#SpringBootTest(classes = TestApplication.class)
#SqlGroup({
#Sql(executionPhase = ExecutionPhase.BEFORE_TEST_METHOD,
scripts = "classpath:data/Setting.sql") })
public class SettingRepositoryIT {
#Mock
private SettingRepository settingRepository;
#Autowired
private Cache applicationCache;
#Test
public void testCachedMethodInvocation() {
List<Setting> firstList = new ArrayList<>();
Setting settingOne = new Setting();
settingOne.setKey("first");
settingOne.setValue("method invocation");
firstList.add(settingOne);
List<Setting> secondList = new ArrayList<>();
Setting settingTwo = new Setting();
settingTwo.setKey("second");
settingTwo.setValue("method invocation");
secondList.add(settingTwo);
// Set up the mock to return *different* objects for the first and second call
Mockito.when(settingRepository.findAllFeaturedFragrances()).thenReturn(firstList, secondList);
// First invocation returns object returned by the method
List<Setting> result = settingRepository.findAllFeaturedFragrances();
assertEquals("first", result.get(0).getKey());
// Second invocation should return cached value, *not* second (as set up above)
List<Setting> resultTwo = settingRepository.findAllFeaturedFragrances();
assertEquals("first", resultTwo.get(0).getKey()); // test fails here as the actual is "second."
// Verify repository method was invoked once
Mockito.verify(settingRepository, Mockito.times(1)).findAllFeaturedFragrances();
assertNotNull(applicationCache.get("findAllFeaturedFragrances"));
// Third invocation with different key is triggers the second invocation of the repo method
List<Setting> resultThree = settingRepository.findAllFeaturedFragrances();
assertEquals(resultThree.get(0).getKey(), "second");
}
}
ApplicationContext, components, entities, repositories and service layer for tests. The reason why I do it this way is because this maven module is used in other modules as a dependency.
#ComponentScan({ "com.persistence_common.config", "com.persistence_common.services" })
#EntityScan(basePackages = { "com.persistence_common.entities" })
#EnableJpaRepositories(basePackages = { "com.persistence_common.repositories" })
#SpringBootApplication
public class TestApplication {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Cache config....
#Configuration
#EnableCaching
public class CacheConfig {
public static final String APPLICATION_CACHE = "applicationCache";
#Bean
public FilterRegistrationBean registerOpenSessionInViewFilterBean() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
OpenEntityManagerInViewFilter filter = new OpenEntityManagerInViewFilter();
registrationBean.setFilter(filter);
registrationBean.setOrder(5);
return registrationBean;
}
#Bean
public Cache applicationCache() {
return new GuavaCache(APPLICATION_CACHE, CacheBuilder.newBuilder()
.expireAfterWrite(30, TimeUnit.DAYS)
.build());
}
}
The repository under test....
public interface SettingRepository extends JpaRepository<Setting, Integer> {
#Query(nativeQuery = true, value = "SELECT * FROM Setting WHERE name = 'featured_fragrance'")
#Cacheable(value = CacheConfig.APPLICATION_CACHE, key = "#root.methodName")
List<Setting> findAllFeaturedFragrances();
}
The first problem with SettingRepositoryIT is, the #Mock anotation on the field settingRepository. This is paradox for any normal-test, integration-test or any else.
You should let Spring bring in the dependencies for the class-under-test, which is SettingRepository in your case.
Please look at this example how #Autowired is used for the class-under-test, which is OrderService in this example:
#RunWith(SpringRunner.class)
// ApplicationContext will be loaded from the
// static nested Config class
#ContextConfiguration
public class OrderServiceTest {
#Configuration
static class Config {
// this bean will be injected into the OrderServiceTest class
#Bean
public OrderService orderService() {
OrderService orderService = new OrderServiceImpl();
// set properties, etc.
return orderService;
}
}
#Autowired
private OrderService orderService;
#Test
public void testOrderService() {
// test the orderService
}
}
Go for the documentation with the full example: ยง 15. Integration Testing
The second problem is that you do not have to test #Cachable. You should only test your implementation. Here is a very good example from Oliver Gierke on how you should test it: How to test Spring's declarative caching support on Spring Data repositories?
In my case I wanted to validate the expression in the unless expression in the #Cacheable annotation, so I think it makes perfect sense and I'm not testing Spring's code.
I managed to test it without using Spring Boot, so it is plain Spring test:
#RunWith(SpringRunner.class)
#ContextConfiguration
public class MyTest {
private static MyCacheableInterface myCacheableInterfaceMock = mock(MyCacheableInterface.class);
#Configuration
#EnableCaching
static class Config {
#Bean
public MyCacheableInterface myCacheableInterface() {
return myCacheableInterfaceMock;
}
#Bean
public CacheManager cacheManager() {
return new ConcurrentMapCacheManager("myObject");
}
}
#Autowired
private MyCacheableInterface myCacheableInterface;
#Test
public void test() {
when(myCacheableInterfaceMock.businessMethod(anyString())).then(i -> {
List<MyObject> list = new ArrayList<>();
list.add(new MyObject(new Result("Y")));
return list;
});
myCacheableInterface.businessMethod("test");
verify(myCacheableInterfaceMock).businessMethod(anyString());
myCacheableInterface.businessMethod("test");
verifyNoMoreInteractions(myCacheableInterfaceMock);
}
}
In MyCacheableInterface I have the following annotation:
public interface MyCacheableInterface {
#Cacheable(value = "myObject", unless = "#result.?[Result.getSuccess() != 'Y'].size() == #result.size()")
List<MyObject> businessMethod(String authorization);
}

#Autowired dependency injection not occurring in junit test

I'm using Spring Boot to bootstrap a spring-data-neo4j application. My unit tests (with no dependencies injected) run fine, but when I try to run an integration test with an #Autowired dependency on a #Service-annotated class, it's failing on a NoSuchBeanDefinitionException.
It seems like the context isn't being loaded in the unit test for some reason, but I've annotated the test with #SpringApplicationConfiguration(classes = AppConfig.class) - is there something else I need to do here?
Configuration class
#Configuration
#EnableAutoConfiguration
#ComponentScan(basePackages = "net.foo.bar")
#EnableNeo4jRepositories(basePackages = "net.foo.bar.repo")
public class AppConfig extends Neo4jConfiguration {
public AppConfig() {
setBasePackage("net.foo.bar");
}
#Bean(destroyMethod = "shutdown")
#Scope(BeanDefinition.SCOPE_SINGLETON)
public GraphDatabaseService graphDatabaseService() {
return new GraphDatabaseFactory().newEmbeddedDatabase(filePath);
}
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(AppConfig.class, args);
}
}
Service class:
package net.foo.bar.core.service
#Service
public class PostService implements EntityService<PostDAO,Post> {
#Autowired
Neo4jTemplate template;
//...
//don't think anything else here is relevant
}
Test class:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = AppConfig.class)
public class PostTests {
#Autowired
PostService postService;
#Test
public void someTest(){
postService.doSomething();
//...
}
}
Stack trace:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'net.foo.bar.PostTests': ....
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [net.foo.bar.core.service.PostService] 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)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1103)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:963)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:858)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:480)
... 31 common frames omitted
Update:
As a workaround, rather than autowiring my service directly, I tried autowiring a reference to the ApplicationContext and instantiating my service through a call to getBeanOfType() in my setUp() method:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = Epublic.class)
public class PostTests {
#Autowired
ApplicationContext ctx;
PostService service;
#Before
public void setUp() {
service = ctx.getBean("postServiceImpl", PostService.class);
}
}
This is working, but I feel like I'm hitting the target but missing the point here...
You don't have basePackages for #ComponentScan. You have only for NeojConfiguration
#Configuration
#EnableAutoConfiguration
#ComponentScan(basePackages = { "net.foo.bar" })
#EnableNeo4jRepositories(basePackages = "net.foo.bar.repo")
public class AppConfig extends Neo4jConfiguration {
public AppConfig() {
setBasePackage("net.foo.bar");
}
#Bean(destroyMethod = "shutdown")
#Scope(BeanDefinition.SCOPE_SINGLETON)
public GraphDatabaseService graphDatabaseService() {
return new GraphDatabaseFactory().newEmbeddedDatabase(filePath);
}
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(AppConfig.class, args);
}
}

Using Spring components in tests

I have a class that looks roughly like this:
#Component
public class MyService {
private MyBean myBean;
#Autowired
public MyService(MyBean myBean) {
this.myBean = myBean;
}
}
I would like to test this class. It would be nice if I could get it to autowire in my tests using a test MyBean object. I tried doing this:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(loader = AnnotationConfigContextLoader.class)
public class MyServiceTest {
#Autowired
MyService myService;
#Configuration
static class ContextConfiguration {
#Bean
public MyBean myBean() {
return createMock(myBean);
}
}
}
When I try to run my tests I get an error like:
Injection of autowired dependencies failed
No matching bean of type MyService found for dependency: expected at least one bean that is a candidate for this dependency.
How can I tell spring to look for my component so it knows how to autowire it?
Thanks.
You should enable component scan
#Configuration
#ComponentScan(basePackages = { MyServicePackage })
static class ContextConfiguration {
...

Spring could not autowire field, No matching bean of type

I try to implement using Spring 3.1.0.RELEASE + Hibernate to make RESTful web service followed this guy's project https://github.com/eugenp/REST
when I run my project is contain error like this.
SEVERE: Context initialization failed
*.BeanCreationException: Error creating bean with name 'userServiceController': Injection of autowired dependencies failed;
*.BeanCreationException: Error creating bean with name 'defaultUserService': Injection of autowired dependencies failed;
*.BeanCreationException: Could not autowire field: private com.cloudlb.dao.UserDAO com.cloudlb.service.DefaultUserService.userDao;
*.NoSuchBeanDefinitionException: No matching bean of type [com.cloudlb.dao.UserDAO]
This is my configuration: (persistence.properties)
ApplicationConfig:
#Configuration
#ComponentScan(basePackages = "com.cloudlb", excludeFilters = { #ComponentScan.Filter(Configuration.class)})
public class ApplicationConfig {
#Bean
public static PropertyPlaceholderConfigurer properties() {
final PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
final Resource[] resources = new ClassPathResource[]{new ClassPathResource("persistence.properties"), new ClassPathResource("restful.properties")};
ppc.setLocations(resources);
ppc.setIgnoreUnresolvablePlaceholders(true);
return ppc;
}
In PersistenceHibernateConfig contain like this:
#Profile("hibernate")
#EnableTransactionManagement
public class PersistenceHibernateConfig { ...
#Bean
public LocalSessionFactoryBean alertsSessionFactoryBean() { ...
#Bean
public DataSource restDataSource() { ...
#Bean
public HibernateTransactionManager transactionManager() { ...
WebConfig:
#Configuration
#EnableWebMvc
public class WebConfig { ... }
So, it start get an error in autowired from here:
UserServiceController:
#Controller
public class UserServiceController {
#Autowired
private UserService userService;
UserService which is implemented by DefaultUserService:
#Service
#Transactional(propagation = Propagation.REQUIRED)
public class DefaultUserService implements UserService {
#Autowired
private UserDAO userDao;
UserDAO:
public interface UserDAO extends GenericDAO<User> { ... }
UserHibernateDAO:
#Profile("hibernate")
public class UserHibernateDAO extends GenericHibernateDAO<User> implements UserDAO{ ... }
GenericHibernateDAO:
#Profile("hibernate")
#Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class GenericHibernateDAO<T extends Serializable> extends AbstractHibernateDAO<T> implements GenericDAO<T> { ... }
And last one AbstractHibernateDAO:
#Transactional( propagation = Propagation.SUPPORTS )
public abstract class AbstractHibernateDAO<T extends Serializable> implements DAO<T> {
private Class<T> clazz;
#Autowired
private SessionFactory sessionFactory;
public AbstractHibernateDAO() {
super();
}
public final void setClazz(final Class<T> clazz) {
this.clazz = clazz;
}
#Override
#Transactional( readOnly = true )
public T findById(String id) {
return (T) this.getCurrentSession().get(this.clazz, id);
}
protected Session getCurrentSession() {
return this.sessionFactory.getCurrentSession();
}
}
I thought it could find UserHibernateDAO. May be I missing something here. So, hope someone know how to fix it. I struck at this problem for 2 day.
I guess there could be a problem in SessionFactory too. Because I start to fix that thing and this came up.
Thank you in advance.
In addition to #Profile("hibernate") the UserHibernateDAO needs an annotation declaring it a Spring bean like #Named or #Component.

Categories