Unable to assign autowired child bean to parent object in Spring Boot - spring

XML Config:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<bean class="com.fossians.maven_courses.Say_Impl" id="id_Say_Impl" />
</beans>
Say_I
public interface Say_I
{
public void Say_I_m1();
}
Say_Impl
public class Say_Impl implements Say_I
{
public void Say_I_m1()
{
System.out.println("inside : public void Say_I_m1() \n");
}
}
Controller :
public class Controller_Test implements SpringApplicationContextInterface
{
#Autowired
private Say_Impl say_Impl;
//Below line not assigning, need to reassign into method
private Say_I say_I = (Say_I) say_Impl;
// private Say_I say_I = (Say_I) applicationContext.getBean("id_Say_Impl");
#RequestMapping(value = "/test10")
public String Test1()
{
say_I = say_Impl;
System.out.println("Say_Impl_auto : "+say_Impl);
System.out.println("Say_I : "+say_I);
say_I.Say_I_m1();
return " request value = test10 ";
}
}
public interface SpringApplicationContextInterface
{
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beanConfig.xml");
}
#SpringBootApplication
#ImportResource("classpath:beanConfig.xml")
public class Courses extends SpringBootServletInitializer
{
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application)
{
return application.sources(Courses.class);
}
}
The above code is part of a spring boot application.
This line of code inside "Controller_Test" class :
private Say_I say_I = (Say_I) say_Impl;
is not assigning Say_Impl object "say_Impl" reference into its parent object say_I. But if i am assigning it again into Test1() method then it is working.
But the below line of code is assigning the say_Impl reference into say_I object.
private Say_I say_I = (Say_I) applicationContext.getBean("id_Say_Impl");
Now my question is, when i am taking the say_impl object by autowiring why i need to reassign it into method? Is there any way to make it working without reassigning?
When i am taking the bean by application context then i need not to reassign, Why?

Very ugly code, legacy xml with spring boot WTF?
Try this
#Autowired
private Say_I say_I;
or better:
#SpringBootApplication
public class Courses {
public static void main(String[] args) {
SpringApplication.run(Courses.class, args);
}
#RestController
public class Controller_Test {
#Autowired
private Say_I say_I;
#RequestMapping(value = "/test10")
public String Test1() {
System.out.println("Say_I : " + say_I);
say_I.Say_I_m1();
return " request value = test10 ";
}
}
#Component
public class Say_I {
void Say_I_m1() {
System.out.println("inside : public void Say_I_m1() \n");
}
}
}

Related

JUNIT - Null pointer Exception while calling findAll in spring Data JPA

I am new to Junits and Mockito, I am writing a Unit test class to test my service class CourseService.java which is calling findAll() method of CourseRepository.class which implements CrudRepository<Topics,Long>
Service Class
#Service
public class CourseService {
#Autowired
CourseRepository courseRepository;
public void setCourseRepository(CourseRepository courseRepository) {
this.courseRepository = courseRepository;
}
public Boolean getAllTopics() {
ArrayList<Topics> topicList=(ArrayList<Topics>) courseRepository.findAll();
if(topicList.isEmpty())
{
return false;
}
return true;
}
}
Repository class
public interface CourseRepository extends CrudRepository<Topics,Long>{
}
Domain class
#Entity
#Table(name="Book")
public class Topics {
#Id
#Column(name="Topicid")
private long topicId;
#Column(name="Topictitle",nullable=false)
private String topicTitle;
#Column(name="Topicauthor",nullable=false)
private String topicAuthor;
public long getTopicId() {
return topicId;
}
public void setTopicId(long topicId) {
this.topicId = topicId;
}
public String getTopicTitle() {
return topicTitle;
}
public void setTopicTitle(String topicTitle) {
this.topicTitle = topicTitle;
}
public String getTopicAuthor() {
return topicAuthor;
}
public void setTopicAuthor(String topicAuthor) {
this.topicAuthor = topicAuthor;
}
public Topics(long topicId, String topicTitle, String topicAuthor) {
super();
this.topicId = topicId;
this.topicTitle = topicTitle;
this.topicAuthor = topicAuthor;
}
}
Following is the Junit class I have written but courseRepository is getting initialized to NULL and hence I am getting NullPointerException.
public class CourseServiceTest {
#Mock
private CourseRepository courseRepository;
#InjectMocks
private CourseService courseService;
Topics topics;
#Mock
private Iterable<Topics> topicsList;
#Before
public void setUp() {
MockitoAnnotations.initMocks(CourseServiceTest.class);
}
#Test
public void test_Get_Topic_Details() {
List<Topics> topics = new ArrayList<Topics>();
Mockito.when(courseRepository.findAll()).thenReturn(topics);
boolean result=courseService.getAllTopics();
assertTrue(result);
}
}
Change the setUp() method to:
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
Probably you are dealing with some problem on the framework to make the mocked class be injected by the framework.
I recommend to use Constructor Injection, so you don't need to rely on the reflection and #Inject/#Mock annotations to make this work:
#Service
public class CourseService {
private final CourseRepository courseRepository;
// #Autowired annotation is optional when using constructor injection
CourseService (CourseRepository courseRepository) {
this.courseRepository = courseRepository;
}
// .... code
}
The test:
#Test
public void test_Get_Topic_Details() {
List<Topics> topics = new ArrayList<Topics>();
Mockito.when(courseRepository.findAll()).thenReturn(topics);
CourseService courseService = new CourseService(courseRepository);
boolean result = courseService.getAllTopics();
assertTrue(result);
}

How to register Converter in Spring Data Rest application

I have Spring converter which uses Spring Data REST's component called EnumTranslator
#Component
public class TranslationStringToSpecificationStatusEnumConverter implements Converter<String, Specification.Status> {
private final EnumTranslator enumTranslator;
#Autowired
public TranslationStringToSpecificationStatusEnumConverter(EnumTranslator enumTranslator) {
this.enumTranslator = enumTranslator;
}
#Override
public Specification.Status convert(String source) {
return enumTranslator.fromText(Specification.Status.class, source);
}
}
Recommended way to register such converter is to subclass RepositoryRestConfigurerAdapter as follows:
#Configuration
public class RepositoryRestConfig extends RepositoryRestConfigurerAdapter {
private final TranslationStringToSpecificationStatusEnumConverter converter;
#Autowired
public RepositoryRestConfig(TranslationStringToSpecificationStatusEnumConverter converter) {
this.converter = converter;
}
#Override
public void configureConversionService(ConfigurableConversionService conversionService) {
conversionService.addConverter(converter);
super.configureConversionService(conversionService);
}
}
When I run the Spring Boot application, it fails on the following:
***************************
APPLICATION FAILED TO START
***************************
Description:
The dependencies of some of the beans in the application context form a cycle:
┌─────┐
| translationStringToSpecificationStatusEnumConverter defined in file ...
↑ ↓
| org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration (field java.util.List org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration.configurers)
↑ ↓
| repositoryRestConfig defined in file ...
└─────┘
So there is circular bean dependency.
How can I register the converter above so that I don't introduce circular bean dependency?
To make it work:
#Override
public void configureConversionService(ConfigurableConversionService conversionService) {
conversionService.addConverter(String.class, Status.class, new StringToTranslatedEnumConverter<>(Status.class));
super.configureConversionService(conversionService);
}
First I created utility class that help me work with Spring beans in unmanaged objects:
#Component
public final class SpringUtils {
#Autowired private ApplicationContext ctx;
private static SpringUtils instance;
#PostConstruct
private void registerInstance() {
instance = this;
}
public static <T> T getBean(Class<T> clazz) {
return instance.ctx.getBean(clazz);
}
}
Then I created the converter:
public class StringToTranslatedEnumConverter<T extends Enum<T> & TranslatedEnum> implements Converter<String, T> {
private final ConcurrentMapCache cache;
private EnumTranslator enumTranslator;
private Class<T> type;
public StringToTranslatedEnumConverter(Class<T> type) {
this.type = type;
cache = new ConcurrentMapCache(type.getName());
}
#Override
public T convert(String from) {
if (enumTranslator == null) {
enumTranslator = SpringUtils.getBean(EnumTranslator.class);
}
Cache.ValueWrapper wrapper = cache.get(from);
if (wrapper != null) {
//noinspection unchecked
return (T) wrapper.get();
}
T translatedEnum = enumTranslator.fromText(type, from);
cache.put(from, translatedEnum);
return translatedEnum;
}
}
UPDATED
TranslatedEnum - it's interface-marker, used to mark enums which translation is only need.
public interface TranslatedEnum {
}
public enum Status implements TranslatedEnum {
CREATED, DELETED
}
The solution to this problem is Spring Core specific. In order to break circle bean dependency cycle, we have to delay setting converter in RepositoryRestConfig. It can be achieved with setter injection:
#Component
public class RepositoryRestConfig extends RepositoryRestConfigurerAdapter {
private TranslationStringToSpecificationStatusEnumConverter converter;
#Override
public void configureConversionService(ConfigurableConversionService conversionService) {
conversionService.addConverter(converter);
super.configureConversionService(conversionService);
}
#Autowired
public void setConverter(TranslationStringToSpecificationStatusEnumConverter converter) {
this.converter = converter;
}
}
You can find how to solve it in this commit by Greg Turnquist: https://github.com/pmihalcin/custom-converter-in-spring-data-rest/commit/779a6477d76dc77515b3e923079e5a6543242da2

Spring advice does not work as expected

I am new in Spring AOP, and I have create an application to learn the Spring AOP, however I found that the Aspect does not work as expected, this is the core code:
Target:
public interface UserService {
void getUserList();
}
#Component
public class UserServiceImpl implements UserService {
#Autowired
private UserDao userDao;
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
#Override
public void getUserList() {
this.userDao.getUserList();
}
}
Aspect:
#Aspect
public class LoggingAspect {
#Pointcut("execution(* com.kk.service.impl.UserServiceImpl(..))")
public void logTargetUserService() {
}
#Before("execution(* com.kk.service.impl.UserServiceImpl.getUserList(..))")
public void logBefore(JoinPoint joinPoint) {
System.out.println("logBefore() is running!");
System.out.println("hijacked : " + joinPoint.getSignature().getName());
System.out.println("******");
}
}
spring.xml:
<context:component-scan base-package="com.kk"/>
<aop:aspectj-autoproxy proxy-target-class="true"/>
Application:
public class Application {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"spring.xml"});
UserServiceImpl userService = context.getBean(UserServiceImpl.class);
userService.getUserList();
}
}
When I run it I only got this output:
get user list at dao
It seems that the advise does not run at all.
What is going on?
You should regist your bean as like this
<bean id="loggingAspect" class="your.package.LoggingAspect"/>

spring 2.5.6 DI issue in jsf application

i get NPE(null pointer exception) each time when i try to insert data into database. help me to resolve this issue. i have import all the necessary libraries which are requried for spring.
this is my applicationContext.xml file where i have configure all the beans.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="personService" class="com.ecommerce.assignment.service.PersonService">
<property name="personDAO" ref="personDAO" />
</bean>
<bean id="personBean" class="com.ecommerce.assignment.bean.PersonBean" />
<bean id="personDAO" class="com.ecommerce.assignment.dao.PersonDAO" />
</beans>
this is interface of person DAO.
public interface IPersonDAO {
public void addPerson(Person instance);
}
this personDAO class implementing IpersonDAO interface and its unimplemented methods.
public class PersonDAO implements IPersonDAO {
#Override
public void addPerson(Person instance) {
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction().begin();
session.saveOrUpdate(instance);
session.getTransaction().commit();
session.close();
}
}
this is interface personService.
public interface IPersonService {
public void addPerson(Person instance);
}
public class PersonService implements IPersonService,Serializable {
private IPersonDAO personDAO;
public IPersonDAO getPersonDAO() {
return personDAO;
}
public void setPersonDAO(IPersonDAO personDAO) {
this.personDAO = personDAO;
}
#Override
public void addPerson(Person instance) {
getPersonDAO().addPerson(instance);
}
}
public class PersonBean implements Serializable {
private static final long serialVersionUID = 1L;
private String emailAddress;
private String password;
private String username;
#ManagedProperty(value = "#{personService}")
private IPersonService iPersonService;
public void addPerson(){
try{
Person person = new Person();
person.setUsername(getUsername());
person.setEmailAddress(getEmailAddress());
person.setPassword(getPassword());
iPersonService.addPerson(person);
}
catch(Exception ex){
ex.printStackTrace();
}
}
}
As your person bean is managed by Spring, you should use #Autowired annotation to make dependency injection, or inject it via XML, as you did for PersonService. You can as well declare the bean as #Component and #Scope.
You error is in injecting service in a bean by using JSF's #ManagedProperty annotation that works solely within JSF context, that is, with JSF managed beans, annotated with #ManagedBean, or declared via XML.

How do i inject a spring bean into a hibernate SequenceGenerator

I have a custom SequenceGenerator written for hibernate:
public class LoginGenerator extends SequenceGenerator {
#Autowired
ITicketService ticketService;
#Override
public Serializable generate(SessionImplementor session, Object obj) {
Ticket ticket = (Ticket) obj;
Long maxCounterOfSection = ticketService.findMaxSectionCounter(ticket
.getSection());
maxCounterOfSection++;
return ticket.getSection() + "-" + maxCounterOfSection;
}
}
But i dont have a spring context inside this generator! ticketService is null. i already tried #Component annotation for my generator, but without success.
PS: Im using spring 3.2.0-FINAL and hibernate 3.6.10-FINAL and there is no way updating to hibernate4!
Any idea, anyone?
Problem solved with ApplicationContextAware class, as described above.
public class ApplicationContextProvider implements ApplicationContextAware {
private static ApplicationContext applicationContext;
#SuppressWarnings("static-access")
#Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = applicationContext;
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
public static <T> T getBean(Class<T> requiredType) {
return applicationContext.getBean(requiredType);
}
public static <T> T getBean(String name, Class<T> requiredType) {
return applicationContext.getBean(name, requiredType);
}
}
In applicationContext.xml I added <bean id="applicationContextProvider" class="de.gfz.rz.spring.ApplicationContextProvider"></bean>.
And here the usage:
public class LoginGenerator extends SequenceGenerator {
#Override
public Serializable generate(SessionImplementor session, Object obj) {
ITicketService ticketService = ApplicationContextProvider
.getBean(ITicketService.class);
Ticket ticket = (Ticket) obj;
Long maxCounterOfSection = ticketService.findMaxSectionCounter(ticket
.getSection());
maxCounterOfSection++;
return ticket.getSection() + "-" + maxCounterOfSection;
}
}

Resources