Spring: autowired service in a component is null - spring

I have created a service:
package tn.ett.medial.service;
#Service
public class ExchangeService {
private Currency EURCurrency;
public Currency getEURCurrency() {
....
return EURCurrency;
}
and a component
package tn.ett.medial.utils.dto;
#Component
public class ProductDTO implements Serializable {
#Autowired
ExchangeService exchangeService;
public ProductDTO() {
}
public ProductDTO(Product product){
System.out.println("service****" + exchangeService);
Currency EURCurrency = exchangeService.getEURCurrency();
}
}
I added the component-scan tag in my application context
<context:component-scan base-package="tn.ett.medial" />
Why the exchangeService is null? (although it works when I inject it into a #Controller).

Since this is a DTO, I guess you do something like ProductDTO productDTO = new ProductDTO();.
So annotated #Autowired ExchangeService is null because Spring doesn't know about the copy of ProductDTO that you created with new and didn't know to autowire it.
Some more info

You run this code:
System.out.println("service****" + exchangeService);
Currency EURCurrency = exchangeService.getEURCurrency();
in a constructor, that is not autowired. No wonder it can not autowire bean, since it is not a bean itself.
The idea of IoC is that Spring Container is creating beans itself.
If you want Spring to use a specific constructor, you have to Autowire it like this:
package tn.ett.medial.utils.dto;
#Component
public class ProductDTO implements Serializable {
private final ExchangeService exchangeService;
public ProductDTO() {
}
#Autowired
public ProductDTO(Product product, ExchangeService exchangeService){
this.exchangeService = exchangeService;
System.out.println("service****" + exchangeService);
Currency EURCurrency = exchangeService.getEURCurrency();
}
}

Related

Spring constructor injection using java config

I have a Class that accepts the following constructor
public Student(int id, String name, Map<String, List<String>> mapInject) {
super();
this.id = id;
this.name = name;
this.mapInject = mapInject;
}
And from spring Java Config, I am injecting the constructor args like below..
#Configuration
public class JavaConfig {
#Bean
public Employee getEmployeeBean() {
Map<String,List<String>> mapInject = new HashMap<String,List<String>>();
//Add map element
return new Employee(3123,"John",mapInject);
}
}
Am i doing constructor injection here? Is this the right way to do so?
I wouldn't use Spring to handle this bean creation, unless you want ALL employees to have the same id and name which I doubt.
The power behind Spring is its Dependency Injection (DI) where you define beans for providers such as database managers, services, etc. and inject those into your components. Defining a #Bean like you have there serves no purpose as now you can only inject employees with an id of 3123 and name John.
It's important to understand that just because you are using Spring it doesn't mean EVERYTHING needs to be handled as a bean - you will always need standard POJOs for housing and passing around state (such as your Employee class) which doesn't need to have anything to do with Spring.
Down the line you might have an EmployeeService for example which houses business logic to fetch employees from a database or something, this could then be configured as a bean so it can be injected across the application.
EDIT
#Configuration
public class JavaConfig {
#Bean
#Autowired //assuming a sessionfactory been is configured elsewhere
public EmployeeService employeeService(final SessionFactory sessionfactory) {
return new EmployeeService(sessionFactory);
}
}
You could then inject this anywhere (maybe in a controller for example):
#RestController
public class EmployeeController {
private final EmployeeService employeeService;
#Autowired
public EmployeeController(final EmployeeService employeeService) {
this.employeeService = employeeService;
}
}
Where the EmployeeController doesn't need to know or care that the userService has a DB connection and doesn't need to worry about configuring it as Spring will handle all of that.

Getting Annotated Spring bean in jsp

I have problem in getting Spring bean from JSP. I have a Spring bean configured using annotation:
#Configuration
public class DefaultServiceConfiguration extends AbstractSpringConfiguration {
#Bean
public ExService exService() {
ExServiceImpl service = new ExServiceImpl();
return service;
}
}
And the ExServiceImpl is as below:
public ExServiceImpl implements ExService {
#Override
public String getApprove(Integer x) {
// .....
return approve;
}
}
Now, I want to acccess the Beans method in JSP:
<c:set var="clientApprove" scope="request" value="${ExService .getApprove(1)}"/>
But it is not working.
What you want to do is not good design at all, and you shall avoid it.
But I believe this will help you:
#Bean(scope=DefaultScopes.REQUEST, name="myBean")
public ExService exService() {
ExServiceImpl service = new ExServiceImpl();
return service;
}
But then the bean will not be singleton.
I think we should add #Service annotation above the ExServiceImpl class to create the bean Service
#Service
public ExServiceImpl implements ExService {
}

Spring annotation based bean injection

So this is basically what I am trying to achieve: Inject User with constructor into UserClass. But it is throwing "No default constructor found" error. As I suspect if I add #Autowired to class User constructor it expects injection there so I'm not really sure where the problem is.
The question might be too basic so you can redirect me to older such questions. There is very little information on annotation based DI.
#Component
public class UserClass {
public User user;
#Autowired
public UserClass(User user) {
this.user = user;
}
}
#Configuration
public class DIconfig {
#Bean
public User getUser() {
return new User('John');
}
}
#Component
public class User {
public String name;
//#Autowired
public User(String name) {
this.name = name;
}
}
Thank you for your time.
You define two beans of the class User, one with #Component, and one with #Bean. The bean configuration with #Bean is fine so far, however the bean definition with #Component is indeed lacking the default constructor. Every bean which is defined with #Component must either have a default constructor or a constructor where all dependencies are autowired. Neither is the case with your bean. So either add a default constructor or remove the #Component and only create beans of that class with an #Bean method.

Fetching global values from database on application startup in Spring boot

I'm writing a Spring Boot / JPA application. I have some values which needs to be visible to the entire application and these values are located in a database. Where should I fetch these values? Should I fetch them in the class containing #SpringBootApplication?
And how do I make it visible to the application? I read that with Spring, we can use a #Bean class to hold global variables. Then do I have to map my #Entity class with a Bean class and autowire the Bean class where ever I want? I'm new to Spring / JPA, so I apologize if the question is basic.
Thanks.
Make a bean that is instantiated with your applicationContext, and use the init-method to run some code after it's instantiated.
A very off the top of my head solution:
In applicationContext.xml:
<bean class="com.example.DbConfigLoader" init-method="init">
A class to load a config entity at startup:
public class DbConfigLoader {
#Autowired
private DbConfigRepository repository;
private DbConfig dbConfig;
public void init(){
dbConfig = repository.findOne(1L);
}
public DbConfig getDbConfig() {
return dbConfig;
}
}
A class representing your config:
#Entity
public class DbConfig {
#Id
private Long id;
private String someSetting;
public String getSomeSetting() {
return someSetting;
}
}
A Spring Data repository for easy database access:
public interface DbConfigRepository extends JpaRepository<DbConfig, Long> {
}

Why Spring #Autowired ApplicationContext appContext is null?

I have Spring bean with annotations:
#Named
#Scope("session")
And this bean property:
#Autowired
ApplicationContext appContext;
The Spring configuration file has entry (that works for other anotations/injections):
<context:component-scan base-package="my.package.name" />
Why appContext is null after such code and configuration?
I am trying to get ApplicationContext (to call getBean(...) on it) and this can be quite involved task (judging from other discussions) in previous Spring versions (e.g. one is required to get ServletContext in Spring web application to create ApplicationContext and getting ServletContext can be quite involved task for beans that don't directly access HTTP Request objects). In Spring 3.x, as I understand, simple #Autwired injection can be used. How AppContext can be accessed?
Here the first problem is you are using #Named which is Java EE annotation and as for as I know Spring yet to support Java EE annotations. Hence instead of using #Named try to use Spring annotation #Service, #Component, #Repository etc.
Here is the example for you I have used JSF Managed bean as well to show how to integrate beans.
#ManagedBean(name="myBacking")
#RequestScoped
public class MyBacking {
private String myText;
#ManagedProperty(value="#{mySpring}")
MySpringBean mySpring;
public String getMyText() {
myText = mySpring.getText();
return myText;
}
public void setMyText(String myText) {
this.myText = myText;
}
public MySpringBean getMySpring() {
return mySpring;
}
public void setMySpring(MySpringBean mySpring) {
this.mySpring = mySpring;
}
}
#Service("mySpring")
#Scope("request")
public class MySpringBean {
#Autowired
MySecond mySecond;
public String getText(){
return "Hello KP" + mySecond.appObj();
}
}
#Service
#Scope("request")
public class MySecond {
#Autowired
ApplicationContext applicationContext;
public String appObj(){
MyThrid mythird =(MyThrid)applicationContext.getBean("myThrid");
return "My Second Bean calld "+ mythird.getTxt();
}
}
#Service
public class MyThrid {
public String getTxt(){
return "from thrid Bean";
}
}

Resources