How to understand #Configuration - spring

I'm new to Java config. I have a code like this. SomeDao has its own dependency, shouldn't we set the dependencies since we are doing new?
Can someone please help me understand this code?
#Configuration
public class DAOConfiguration {
#Bean(name = "someDao")
public SomeDao someDao() {
return new SomeDao();
}

Are you familiar with how this is done in xml? It is extremely similar to that.
Here is an example of SomeDao being configured with Dep1 (via constructor injection) and Dep2 (via setter injection) in xml:
<bean id="someDao" class="com.example.SomeDao">
<constructor-arg ref="dep1"/>
<property name="dep2" ref="dep2"/>
</bean>
<bean id="dep1" class="com.example.Dep1" />
<bean id="dep2" class="com.example.Dep2" />
This same example in JavaConfig would be configured as such:
#Configuration
public class DAOConfiguration {
#Bean(name = "someDao")
public SomeDao someDao() {
final SomeDao someDao = new SomeDao(dep1());
someDao.setDep2(dep2());
return someDao;
}
#Bean(name="dep1")
public Dep1 dep1() {
return new Dep1();
}
#Bean(name-"dep2")
public Dep2 dep2() {
return new Dep2();
}
}
All three beans are still registered with the ApplicationContext too, so you can have all three of these beans autowired into another class, like so:
#Controller
public class MyController {
#Autowired
private SomeDao someDao;
#Autowired
private Dep1 dep1;
//...some methods
}

Related

Autowired bean giving Null Pointer Exception

I am using Autowired annotation in a Service class to inject Dao dependency. The code I have written is:
public interface Service {
public List<String> getAllCountries() ;
}
public class ServiceImpl implements Service {
#Autowired
private TestDao testDao;
public TestDao getTestDao() {
return testDao;
}
public void setTestDao(TestDao testDao) {
this.testDao = testDao;
}
public List<String> getAllCountries() {
// TODO Auto-generated method stub
System.out.println("coming in here:" + testDao);
return testDao.getAllCountries();
}
}
public interface TestDao {
List<String> getAllCountries() ;
}
public class TestDaoImpl implements TestDao{
#Override
public List<String> getAllCountries() {
// TODO Auto-generated method stub
List<String> ls = new ArrayList<>();
ls.add("test1");
return ls;
}
}
And a controller
public class TestController {
public void doSth() {
Service service = new ServiceImpl();
try {
System.out.println("service obj:" + service);
List<String> list = service.getAllCountries();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Beans.xml:
<context:annotation-config/>
<bean id="controller" class="org.test.TestController"/>
<bean id="testDao" class="org.test.TestDaoImpl"/>
And a main class:
ApplicationContext context = new
ClassPathXmlApplicationContext("beans4.xml");
TestController obj= (TestController) context.getBean("controller");
obj.doSth();
But it is throwing NullPointerException in ServiceImpl class. These all classes are in the same package.
Can somebody help me understand what exactly is the issue?
Solution:
public class TestController {
#Autowired
Service service;
//remaining code as it is
}
Your Service class is not managed by Spring . Hence, the dependency is getting injected.
To make your service class managed,
You can use #Service stereo type annotation and do a component scan.
I mean,
package com;
#Service
public class ServiceImpl implement XXXX{
//Your changes
}
and in spring config file:
<context:component-scan base-package="com"/>
I did not see any bean declaration or annotation for the ServiceImpl.
//You canot do it like the following
#controller
class A{
ServiceImpl simp=new ServiceImpl();
}
class ServiceImpl{
#Autowired
Adao adoa;//throws NPE
}
//it should be like this
#Controller
class A{
#autowired
ServiceImpl simp;
}
#Service
class ServiceImpl{
#Autowired
Adao adoa;
}
#Repository
class Adao{
}
Your testDao dependency bean has not been injected and you need the Spring container that you are using annotations and also specify which packages need to be scanned for Autowiring by adding the following:
<context:annotation-config />
<context:component-scan base-package="org.test" />
You can look here on how you can auto wire spring beans.

Spring #Configuration classes, how to configure multiple instances of the same bean passing different parameters

I have a Spring Java Configuration class that defines a bean inside, e.g.:
#Configuration
public class SomeConfig{
private String someProperty;
public SomeConfig(String someProperty){
this.someProperty=someProperty;
}
#Bean
public SomeBean someBean(){
SomeBean s = new SomeBean(someProperty);
return s;
}
}
I need to have several instances of SomeBean, each of them configured with a different someProperty value.
In a Spring Boot application is it possible to #Import the same class multiple times?
SELF-ANSWERED: If you import the same #Configuration class, it will override the existing one.
How can something like this be done with Spring Java Config?
UPDATE:
In XML I can do:
<bean class="x.y.z.SomeBean">
<constructor-arg value="1"/>
</bean>
<bean class="x.y.z.SomeBean">
<constructor-arg value="2"/>
</bean>
I am looking for an equivalent with Java Config
I just had to use another #Configuration class that defined as many SomeConfig beans as needed:
#Configuration
public class ApplicationConfig{
#Bean
public SomeConfig someConfig1(){
return new SomeConfig("1");
}
#Bean
public SomeConfig someConfig2(){
return new SomeConfig("2");
}
}
#Configuration
public class SomeConfig{
private String someProperty;
#Bean
public OtherBean otherBeanOne(){
OtherBean otherBean = new OhterBean();
otherBean.setSomeBean(someBean("property1"));
return otherBean;
}
#Bean
public OtherBean otherBeanTwo(){
OtherBean otherBean = new OhterBean();
otherBean.setSomeBean(someBean("property2"));
return otherBean;
}
#Bean
public SomeBean someBean(String someProperty){
SomeBean s = new SomeBean(someProperty);
return s;
}
}

Spring Boot #Transactional not working when on #Service class (instead of controller)

I thought it was best practice to put the #Transactional annotation on the service layer classes and not on the controllers (see f.e. Why we shouldn't make a Spring MVC controller #Transactional?). But this not working on my Spring Boot application. Why is that?
The registerAction method in the controller (see code below) performs multiple service calls. When f.e. the mailService.sendActivationMail(...) fails, I want to rollback the inserted user from the userService.registerUser(...) call. Do I need to put the #Transactional annotation on the controller class or not?
My Spring Boot application correctly uses transactions when the #Transactional annotation is set on the controller class:
AuthController.java
#RestController
#RequestMapping("/api/auth")
#Transactional
public class AuthController {
#Autowired
private UserService userService;
#Autowired
private ProfileService profileService;
#Autowired
private MailService mailService;
#RequestMapping(path = "register", method = RequestMethod.POST)
public Profile registerAction(#Valid #RequestBody Registration registration) {
ApiUser user = userService.registerUser(registration);
Profile profile = profileService.createProfile(user, registration);
mailService.sendActivationMail(user);
return profile;
}
}
but transactions don't work when the #Transactional annotation is set on the Service classes instead (and not on the controller):
UserService.java
#Service
#Transactional
public class UserService {
#Autowired
private ApiUserRepository userRepository;
public ApiUser registerUser(Registration registration) {
...
userRepository.save(user);
...
}
}
My configuration classes:
SpringApiApplication.java
#SpringBootApplication
public class SpringApiApplication {
public static void main(String[] args) {
SpringApplication.run(SpringApiCommonApplication.class, args);
}
}
ApiConfiguration.java
#Configuration
#EnableJpaAuditing
#EnableTransactionManagement
public class ApiConfiguration {
#Autowired
private ApiProperties properties;
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
public UsernameCanonicalizer usernameCanonicalizer() {
return new UsernameCanonicalizer();
}
#Bean
public EmailCanonicalizer emailCanonicalizer() {
return new EmailCanonicalizer();
}
#Bean
public ApiTokenHandler activationTokenHandler() {
return new StandardApiTokenHandler(properties.getActivationTokenDuration());
}
}
#M.Deinum got me on the right track. Spring (boot) doesn't automatically wrap your controller calls in a transaction like other frameworks do. So you have to either add a #Transactional annotation to your controller, or move the code from the controller class to a service class.
Moving the code from the controller class to a service class is the better thing to do since (amongst other things) makes the code better testable. So that's what I did.
AuthenticationService.java
#Service
public class AuthenticationService {
#Autowired
private UserManager userManager;
#Autowired
private ProfileManager profileManager;
#Autowired
private MailManager mailManager;
#Transactional
public Profile registerUser(Registration registration) {
ApiUser user = userManager.registerUser(registration);
Profile profile = profileManager.createProfile(user, registration);
mailManager.sendActivationMail(user);
return profile;
}
...
}
AuthController.java
#RestController
#RequestMapping("/api/auth")
public class AuthController {
#Autowired
private AuthenticationService authenticationService;
#RequestMapping(path = "register", method = RequestMethod.POST)
#ApiOperation(value = "Registers a user")
public Profile register(#Valid #RequestBody Registration registration) {
return authenticationService.registerUser(registration);
}
...
}
You can place the #Transactional annotation before an interface definition, a method on an interface, a class definition, or a public method on a class. However, the mere presence of the #Transactional annotation is not enough to activate the transactional behavior.
The #Transactional annotation is simply metadata that can be consumed by some runtime infrastructure that is #Transactional-aware and that can use the metadata to configure the appropriate beans with transactional behavior.
In the preceding example, the <tx:annotation-driven/> element switches on the transactional behavior.
// Below is the service class that we want to make transactional
#Transactional
public class DefaultEmployeeService implements EmployeeService {
void insertEmployee(Employee Employee);
void updateEmployee(Employee Employee);
}
XML Configuration:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" ...>
<!-- this is the service object that we want to make transactional -->
<bean id="employeeService" class="service.DefaultEmployeeService"/>
<!-- enable the configuration of transactional behavior based on annotations -->
<tx:annotation-driven transaction-manager="txManager"/>
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- (this dependency is defined somewhere else) -->
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
Some points that you can try:
Do all above mentioned configurations.
Remove #Transactional configuration from Controller.
Reference the Service object along with Transaction manager bean.
More Details: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/transaction.html

an annotation to avoid setter method?

If I specify what should be injected into a property, like
<property name="xxx" ref="some_bean" />
or
<property name="xxx">
<bean .../>
</property>
then I have to write a setter method.
May I use some annotation to avoid this like #autowired?
You can do this with constructor injection. 3 main ways to do this:
XML:
<bean id="beanA" class="com.BeanA">
<constructor-arg ref="beanB"/>
</bean>
<bean id="beanB" class="com.BeanB"/>
JavaConfig:
#Configuration
public class MyConfig {
#Bean
public BeanA beanA() {
return new BeanA(beanB());
}
#Bean
public BeanB beanB() {
return new BeanB();
}
}
Autowiring:
#Component
public class BeanA {
private final BeanB beanb;
// This assumes that there is a BeanB in your application context already
#Autowired
public BeanA(final BeanB beanB) {
this.beanB = beanB;
}
}
You can take Autowiring even further, and wire directly to the field:
#Component
public class BeanA {
// This assumes that there is a BeanB in your application context already
#Autowired
private final BeanB beanb;
}

Spring dependency injection and generic class

Sorry for my English. I can not to do dependency injection for generic class in spring. Generic class:
abstract class BaseBO<Id, Entity, DAOClass extends DAO<Id, Entity>> implements BO<Id, Entity, DAOClass> {
DAOClass dao;
public DAOClass getDAO() {
return dao;
}
//...
}
Use generic class:
public class TaskBO extends BaseBO<Long, Task, TaskDAO> implements BO<Long, Task, TaskDAO> {
}
I want to do dependency injection in a class TaskBO for property TaskDAO.
But I can only to set dependency TaskDAO via a interface DAO for bean TaskBO:
<bean id="TaskBO" class="com.otv.model.bo.TaskBO">
<property name="DAO" ref="TaskDAO" />
</bean>
<bean id="TaskDAO" class="com.otv.model.dao.TaskDAO">
<property name="sessionFactory" ref="SessionFactory" />
</bean>
How to set dependency injection via class TaskDAO?
Attach stacktrace with error if you have one.
Before all use consistent case for property accessor:
abstract class BaseBO<Id, Entity, DAOClass extends DAO<Id, Entity>> implements BO<Id, Entity, DAOClass> {
DAOClass dao;
public DAOClass getDao() {
return dao;
}
//...
}
Most probably you need a setter for BaseBO.dao property
public void setDao(DAOClass dao) {
this.dao = dao;
}
or
public class TaskBO extends BaseBO<Long, Task, TaskDAO> implements BO<Long, Task, TaskDAO> {
public void setDao(TaskDAO dao) {
super.dao = dao;
}
}

Resources