myMessageListener is indeed in the IOC, but why isn't it available. When I use to remove #Component, it is not managed by IOC, and when I create a new object, it will not be prompted to be empty. What's going on?
complete error: Bean instantiation via constructor failed;
nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.demo.cache.redis.Subscriber]: Constructor threw exception;
nested exception is org.springframework.data.redis.RedisSystemException: Unknown redis exception;
nested exception is java.lang.IllegalArgumentException: MessageListener must not be null!
#Slf4j
#Component
class MyMessageListener implements MessageListener {
#Override
public void onMessage(Message message, byte[] bytes) {
log.info("Receive message : " + message);
}
}
#Slf4j
#Service
public class Subscriber {
// private MyMessageListener myMessageListener = new MyMessageListener(); --Success
/**
* error: nested exception is java.lang.IllegalArgumentException: MessageListener must not be null!
*/
#Autowired
private MyMessageListener myMessageListener;
public Subscriber(StringRedisTemplate redisTemplate) {
RedisConnection redisConnection = redisTemplate.getConnectionFactory().getConnection();
redisConnection.subscribe(myMessageListener, Publish.CHANNEL.getBytes(StandardCharsets.UTF_8));
}
}
Related
I'm trying to write test with bean classes as innerClasses.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes={SpringContextConfigurationClassesExample.BeanA.class})
public class SpringContextConfigurationClassesExample {
#Autowired
private SpringContextConfigurationClassesExample.BeanA beanA;
#Test
public void verifyBeans() {
assertNotNull(beanA);
}
#Component
public class BeanA {
public BeanA(){}
}
}
But have an exception:
Caused by: org.springframework.beans.BeanInstantiationException:
Failed to instantiate
[com.javarticles.spring.SpringContextConfigurationClassesExample$BeanA]:
No default constructor found; nested exception is
java.lang.NoSuchMethodException:
com.javarticles.spring.SpringContextConfigurationClassesExample$BeanA.()
Is it possible and how to write this test ?
Use Static Nested Class instead Member Inner Class.
#Component
static public class BeanA {
public BeanA(){}
}
I have a Spring Boot app and #Component class which looks like:
#Component
public class CustomEvent {
#Autowired
ApplicationEventPublisher publisher;
#PreRemove
public void onItemDelete(Object entity) {
System.out.println(" =======PUBLISH====== " + entity);
publisher.publishEvent(new EntityDeleteEvent<>(entity));
}
}
When it goes to run above method the first line is printed with proper entity but the publisher.publishEvent line throws a NullPointerException. I suppose it that the ApplicationEventPublisher is not being #Autowired but couldn't find why. Other #Components which are in the app are found by #ComponentScanner.
Of course in my entity this CustomEvent is registered:
#Entity
#EntityListeners(
CustomEvent.class
)
#Data
#AllArgsConstructor
public class Item
The exact error which is thrown looks like:
2017-10-26 16:46:06.190 ERROR 10176 --- [io-8091-exec-10] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause
java.lang.NullPointerException: null
at com.inventory.events.CustomEvent.onItemDelete(CustomEvent.java:19)
Do you have any suggestion why publisher is null?
The initialisation of ApplicationEventPublisher doesn't happen OR will remain null, if you have created the CustomeEvent without the help of Bean (like CustomEvent event = new CustomEvent().
Instead, declare the CustomEvent as bean in your configuration (Spring) and get the CustomEvent using application context.
If CustomEvent is in the Spring's package scan, then I don't know.
But, there is an additional solution.
Create a class to instantiate spring managed class, but by ApplicationContext.
1 - Create the class below:
public class AppContextUtil implements ApplicationContextAware {
private static ApplicationContext context;
#Override
public void setApplicationContext(ApplicationContext appContext) throws BeansException {
context = appContext;
}
public static ApplicationContext getApplicationContext() {
return context;
}
public static <T> T getBean(Class<T> classe) {
return context.getBean(classe);
}
}
2 - Instance class as below:
public class CustomEvent {
private ApplicationEventPublisher publisher;
#PreRemove
public void onItemDelete(Object entity) {
System.out.println(" =======PUBLISH====== " + entity);
getApplicationEventPublisher().publishEvent(new EntityDeleteEvent<>(entity));
}
private ApplicationEventPublisher getApplicationEventPublisher() {
return AppContextUtil.getBean(ApplicationEventPublisher.class);
}
}
I am trying to integrate Spring JPA with MongoDB. My intention is to just retrieve data from mongo DB. I am getting the below error while injecting my repository.
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mongoService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.org.coop.society.data.mongo.repositories.MaterialMasterRepository com.org.coop.security.service.MongoService.materialMasterRepository; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'materialMasterRepository': Invocation of init method failed; nested exception is java.lang.AbstractMethodError
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1210)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
My configuration snippet is given below.
TestMongoDBConfig.java
#Configuration
#EnableMongoRepositories(basePackages = {"com.abc.data.mongo.repositories"})
#ComponentScan(basePackages = "com.abc")
#PropertySource("classpath:applicationTest.properties")
public class TestMongoDBConfig extends AbstractMongoConfiguration {
#Autowired
private Environment env;
#Override
protected String getDatabaseName() {
return "retail";
}
#Override
#Bean
public MongoClient mongo() throws Exception {
MongoClient client = new MongoClient("localhost", 27017);
return client;
}
#Override
protected String getMappingBasePackage() {
return "com.abc.data.mongo.entities";
}
#Bean
public MongoTemplate mongoTemplate() throws Exception {
return new MongoTemplate(mongo(), getDatabaseName());
}
}
MaterialMaster.java in com.abc.data.mongo.entities package
#Document(collection = "materialMaster")
public class MaterialMaster {
#Id
private Long materialId;
#Field
private String name;
MaterialMasterRepository.java in com.abc.data.mongo.repositories package
public interface MaterialMasterRepository extends MongoRepository<MaterialMaster, Long> {
}
MongoService.java in com.abc.service package
#Service
public class MongoService {
#Autowired
private MaterialMasterRepository materialMasterRepository;
public void getMaterials() {
List<MaterialMaster> materials = materialMasterRepository.findAll();
System.out.println(materials);
}
}
Junit class looks like below
#RunWith(SpringJUnit4ClassRunner.class)
#ComponentScan(basePackages = "com.abc")
#ContextHierarchy({
#ContextConfiguration(classes={TestMongoDBConfig.class})
})
public class ModuleWSTest {
#Autowired
private MongoService mongoService;
#Test
public void testModule() {
mongoService.getMaterials();
}
}
I have tried all possible changes (as per my knowledge) but no luck. Any help is really appreciated.
The error message is little confusing. I was using latest spring-data-mongodb (1.8.4.RELEASE). Once I downgraded the dependency to 1.6.0.RELEASE then the above configuration started working.
Configuration
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled=true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration{
#Override
protected AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager();
}
}
Controller
#RequestMapping(value="/events/eventsToApprove", method=RequestMethod.GET, produces=MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
#PreAuthorize("hasRole('ROLE_LEAD')")
public List<Event> eventsToApprove(#RequestParam("user") String username){
CustomUser user= (CustomUser) userService.loadUserByUsername(username);
if(user!=null){
return eventService.getEventsToApprove(user);
}
return null;
}
Error
Unexpected AOP exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'methodSecurityInterceptor' defined in com.tracker.config.MethodSecurityConfig: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: An AuthenticationManager is required
I am using #preauthorize on the above controller to allow only users with "ROLE_LEAD". but it's not working. Every request is coming in. Anything wrong in configiration
Thanks
i am trying to run full package of junit test classes, and i have an audit classes for my domain classes as follows:
#PrePersist
public void prePersist(AuditableEntity e) {
UserService userService = SpringBeanFactory.getBean(UserService.class);
// some auditing here
}
- SpringBeanFactory class:
public class SpringBeanFactory {
private static ApplicationContext applicationContext;
public static <T> T getBean(final String name, final Class<T> requiredType) {
T bean = null;
if (applicationContext != null) {
bean = applicationContext.getBean(name, requiredType);
}
return bean;
}
public static <T> T getBean(final Class<T> requiredType) {
T bean = null;
if (applicationContext != null) {
bean = applicationContext.getBean(requiredType);
}
return bean;
}
public static void setApplicationContext(final ApplicationContext applicationContext) {
if (SpringBeanFactory.applicationContext == null) {
SpringBeanFactory.applicationContext = applicationContext;
}
}
}
-Test class config:
#Autowired
private ApplicationContext applicationContext;
#Before
public void before() throws Exception {
SpringBeanFactory.setApplicationContext(applicationContext);
}
-SpringTestingConfig class:
#Configuration
#ComponentScan(basePackages = "com.myapp.data", excludeFilters = { #Filter(Configuration.class) })
#PropertySource("classpath:/test.properties")
#Profile("test")
public class SpringTestingConfig {
private static Logger log = (Logger)LoggerFactory.getLogger(SpringTestingConfig.class);
#Autowired
private ApplicationContext applicationContext;
#Bean
public DataSource XdataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
if(log.isDebugEnabled()) log.debug("profile.name", "test");
System.setProperty("profile.name", "test");
dataSource.setDriverClassName("org.h2.Driver");
String schemaName = ConfigurationUtil.config().getString("db.schema.name").toLowerCase();
log.debug("SCHEMA IS " + schemaName);
String url = "jdbc:h2:mem:test;MODE=Mysql;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;INIT=CREATE SCHEMA IF NOT EXISTS " +schemaName +"\\;" + "SET SCHEMA "+schemaName;
dataSource.setUrl(url);
//dataSource.setUrl("jdbc:h2:mem:test;MODE=Mysql;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;INIT=CREATE SCHEMA IF NOT EXISTS " + schemaName);
dataSource.setUsername("sa");
//use your own local mysql in tests here...
// dataSource.setDriverClassName("com.mysql.jdbc.Driver");
// dataSource.setUrl("jdbc:mysql://localhost:3306/mv_tests?characterEncoding=UTF-8");
// dataSource.setUsername("tomcat");
// dataSource.setPassword("tomcat");
//
return dataSource;
}
#Bean
public DataSource dataSource() {
SpringBeanFactory.setApplicationContext(applicationContext);
LoggerUtils.setAllApplicationLogs("DEBUG");
DriverManagerDataSource dataSource = new DriverManagerDataSource();
if(log.isDebugEnabled()) {
log.debug("profile.name", "test");
}
System.setProperty("profile.name", "test");
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
String schemaName = ConfigurationUtil.config().getString("db.schema.name");
String username = ConfigurationUtil.config().getString("db.username");
String password = ConfigurationUtil.config().getString("db.password");
if( log.isDebugEnabled() ) {
log.debug( "SCHEMA IS " + schemaName );
log.debug( "Username IS " + username );
log.debug( "Password IS " + password );
}
dataSource.setUrl("jdbc:mysql://localhost:3306/"+schemaName);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
}
-Test class annotations:
#RunWith(SpringJUnit4ClassRunner.class)
#TestExecutionListeners({ WebContextTestExecutionListener.class, DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class, TransactionalTestExecutionListener.class })
#ActiveProfiles("test")
#DirtiesContext
#ContextConfiguration(loader = AnnotationConfigContextLoader.class, classes = { SpringConfig.class, SpringTestingConfig.class, SpringLocalContainerJPAConfig.class, CustomConfiguration.class })
#Transactional
when my test method tries to save an entity, it makes call to PrePersist method which in turn makes call to the getting spring service:
UserService userService = SpringBeanFactory.getBean(UserService.class);
which in turns produces the following exception:
Error creating bean with name 'userService':
Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException:
Could not autowire field: private com.motivosity.data.repository.UserRepository com.motivosity.service.impl.UserServiceImpl.userRepository;
nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userRepositoryImpl':
Injection of persistence dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'springLocalContainerJPAConfig': Injection of autowired dependencies failed;
nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field:
javax.sql.DataSource com.motivosity.data.config.SpringLocalContainerJPAConfig.dataSource;
nested exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'springTestingConfig': Initialization of bean failed;
nested exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'org.springframework.cache.annotation.ProxyCachingConfiguration':
Initialization of bean failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
No bean named 'org.springframework.context.annotation.ConfigurationClassPostProcessor.importRegistry' is defined
i have to mention that this exception occurs when running full package of test classes, but when running this test class separately no exception is produced.
BTW, i am using spring 3.2.3.RELEASE
UPDATE: when i upgraded the spring version to latest release 4.0.3, i am getting a new exception on the same get UserService line:
org.springframework.context.support.GenericApplicationContext#3aa54263 has been closed already
please advise how to fix this exception.
When you annotate a test class or test method with #DirtiesContext, you are telling Spring to close the ApplicationContext after that test class or method. Thus, if you later attempt to retrieve a bean from a closed context you will get an exception like you're seeing.
My guess is that you are using #DirtiesContext in other test classes within your test suite, and a result the logic in SpringBeanFactory.setApplicationContext() is broken since it can potentially maintain a reference to a closed context. Thus, you'll need allow the current ApplicationContext to be set for each test. In other words, remove the null-check like follows
public static void setApplicationContext(final ApplicationContext applicationContext) {
// always set the current context
SpringBeanFactory.applicationContext = applicationContext;
}
Hope this helps!
- Sam (author of the Spring TestContext Framework)