Spring Autowire Without Setter Method - java

I am new to spring. I am attempting to autowire TestDAO without setter method. But i failed to autowire.
System.out.println("TestClass.testDAO "+testDAO); It returns null.
Kindly help me to unlock.
My xml config :
<context:component-scan base-package="com.test" />
<context:annotation-config/>
<bean id="testClass" class="com.test.TestClass" autowire="byName">
</bean>
Java classes :
#Component
public class TestClass {
#Autowired(required=true)
public TestDAO testDAO = null;
{
System.out.println("TestClass.testDAO "+testDAO);
}
}
#Repository
public class TestDAO{
}

Here's an example about how to fix your code:
#Component
public class TestClass {
#Autowired(required=true)
public TestDAO testDAO;
// When someone calls this method, the testDao component should
// be initialized with TestDAO instance.
public void someMethod(){
System.out.println("TestClass.testDAO "+testDAO);
}
}
public interface TestDAO extends JpaRepository<MyEntity, Long>{
}
Also, you could use the #Autowired annotation in a constructor.
#Component
public class TestClass {
public TestDAO testDAO;
#Autowired
public TestClass(TestDAO testDAO){
this.testDAO = testDAO;
System.out.println("TestClass.testDAO "+testDAO);
}
}
Hope it helps,

Related

Field ClientService required a bean that could not be found in Spring

This is my ClientService class :
public interface ClientService{
public void saveClient(Client client);
}
This is the implementation :
#Service("clientService")
public class ClientServiceImpl{
#Autowired
private ClientRepository clientRepository;
public void saveClient(Client client) {
clientRepository.save(survey);
}}
This is my repository:
#Repository("clientRepository")
public interface ClientRepository extends JpaRepository<Client, Long> { }
And in my controller I have :
#Controller
public class LoginController {
#Autowired
private ClientService clientService;
which I then try to access
clientService.save in the function.
What annotation could I possibly be missing or what am I doing wrong ?
Cuz I've done this the same way before and it has worked for other services.
Thank you
Fixed it!
I had forgotten implements ClientService in the ClientServiceImplementation class!

How to implement DI in Spring MVC.?

I have a confusion in Dependency Injection in Spring MVC.
First Code:-
#Service
#Transactional
public class UserServiceImpl implements UserService {
#Autowired
private Userdao udo;
#Override
#Transactional
public List<Positions> plist() {
return udo.plist();
}
}
It is working Fine.
I would like to implement Dependency Injection in this class.Am doing right or wrong?
second code:-
`#Service
#Transactional
public class UserServiceImpl implements UserService {
#Autowired
private Userdao udo;
public UserServiceImpl(Userdao udo) {
this.udo = udo;
}
#Override
#Transactional
public List<Positions> plist() {
return udo.plist();
}
}
Its not working.ERROR: org.springframework.web.context.ContextLoader - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'homeController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.xxx.Services.UserService com.xxx.java.HomeController.uservice; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userServiceImpl' defined in file [D:\xxxWorkspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp1\wtpwebapps\abcd\WEB-INF\classes\com\xxx\ServiceImp\UserServiceImpl.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.xxx.ServiceImp.UserServiceImpl]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.xxx.ServiceImp.UserServiceImpl.<init>()
I am a beginner .please help me to solve this.How to implement DI in Spring MVC.
You can do this two ways.
You can use field based autowiring. But in this case you will need a default constructor.
#Service
#Transactional
public class UserServiceImpl implements UserService {
#Autowired // field based DI
private Userdao udo;
// default constructor
public UserServiceImpl() {}
#Override
#Transactional
public List<Positions> plist() {
return udo.plist();
}
}
You can use constructor based dependency injection. To do this simply move your #Autowire annotation to your constructor. And remove it from the field.
#Service
#Transactional
public class UserServiceImpl implements UserService {
private Userdao udo;
#Autowired // constructor based DI
public UserServiceImpl(Userdao udo) {
this.udo = udo;
}
#Override
#Transactional
public List<Positions> plist() {
return udo.plist();
}
}
First setup is alright, and should work.
In the second setup you're getting following exception
class [com.xxx.ServiceImp.UserServiceImpl]: No default constructor found;
Which means what it says, since you've defined a constructor public UserServiceImpl(Userdao udo) Spring can't find an no-argument constructor.
You can either remove this constructor and use the first one or you can define the no argument constructor yourself.
You shouldn't actually need to define a constructor in a bean as you're not going to create bean object yourself. You would only need it if you're autorwiring constructor arguments.
If you're trying to autowire constructor then you can do it like below.
#Service
#Transactional
public class UserServiceImpl implements UserService {
private Userdao udo;
#Autowired //autowired constructor, instead of the field
public UserServiceImpl(Userdao udo) {
this.udo = udo;
}
#Override
#Transactional
public List<Positions> plist() {
return udo.plist();
}
}
In simple words: If you define a constructor (overloaded) then you must use the #Autowired annotation on the constructor, if you do not define a constructor, then you must use the #Autowired annotation for each Object you need to add as dependency injection. For example:
With constructor overloaded:
#Service
#Transactional
public class UserServiceImpl implements UserService {
private final Userdao userDao;
private final RoleDao roleDao;
#Autowired
public UserServiceImpl(Userdao userDao, RoleDao roleDao) {
this.userDao = userDao;
this.roleDao = roleDao;
}
}
Without constructor overloaded
#Service
#Transactional
public class UserServiceImpl implements UserService {
#Autowired
private UserDao userDao;
#Autowired
private RoleDao roleDao;
// default constructor
public UserServiceImpl() {}
}
Defining a constructor with a single #Autowired is better than having many objects #Autowired

How to extend #Service?

Here is a sample class below:
#Service("testService")
public class TestService {
public String something() {
return "abc";
}
}
I want to extend the class and let the container know that it needs to pick up my extended class from now.
#Service("extendedTestService")
public class ExtendedTestServiceMock extends TestService {
#Override
public String something() {
return "xyz";
}
}
Test class:
public class TestClass extends SpringTest {
#Autowired
#Qualifier("extendedTestService")
private ExtendedTestService testService;
public void testMethod() {
......
}
}
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [TestService] is defined: expected single matching bean but found 2: ExtendedTestServiceMock,testService
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:865) ~[spring-beans-3.2.8.RELEASE.jar:3.2.8.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:770) ~[spring-beans-3.2.8.RELEASE.jar:3.2.8.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:489) ~[spring-beans-3.2.8.RELEASE.jar:3.2.8.RELEASE]
... 91 common frames omitted
How to resolve it?
Try using interfaces.
public interface TestService {
String something();
}
Implementations:
#Service
#Qualifier("testService")
public class TestServiceImpl implements TestService { ... }
#Service
#Qualifier("testServiceMock")
public class TestServiceMockImpl implements TestService { ... }
And the test class:
public class TestClass extends SpringTest {
#Autowired
#Qualifier("extendedTestService")
private TestService testService;
...
}
One solution that would work in your case is the #Primary annotation.
Your TestServiceMockImpl would look like:
#Service("extendedTestService ")
#Primary
public class ExtendedTestServiceMock extends TestService {
#override
public String something() {
return "xyz";
}
}
Check out this for more details on #Primary
I however suggest that you don't follow the above solution (since this will get out of hand very quick if you start using #Primary everywhere), that you instead take a look at Spring Profiles
There are a lot of way you could create your Spring configuration using profiles, but regardless of how you end up configuring the beans, the end result would be a more clean design.
If you have an identifier to help you decide which service to initialize, then you can use ConditionlOnProperty annotation
Ex:
#Service
#ConditionlOnProperty(value = "test.service.extension.enabled")
public class TestService {
}
#Service
#ConditionlOnProperty(value = "test.service.extension.enabled", havingValue = "false")
public class ExtendedTestServiceMock extends TestService {
}
If you want to use the extended test service, you can set the property test.service.extension.enabled=true in your application.properties
It depends on your definition order if your service define on the xml file.
Otherwise, you could use a BeanFactoryPostProcessor to do this, which is only registered in the test scenarios that you want this mocked.
public class SystemTestBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
#Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory factory) throws BeansException {
// put your custom code in here
}
}
Or you can use #DependsOn to make sure the parent bean should be deploy firstly then your extend bean
#Service("testService")
#DependsOn("testService")
public class ExtendedTestService extends TestService {
}
Hope this helps.

How to Autowire a 1-arg Object Constructor with Previously Autowired Object?

Given the following MyConstructorClass:
#Component
public class MyConstructorClass{
MyObj var;
public MyConstructorClass( MyObj constrArg ){
this.var = var;
}
...
}
How can I autowire a field that requires a constructor argument from a previously #Autowired field? Below is an example.
Note - this question, I believe, is similar to this one, except that my constructor argument is not a String. This code sample is slightly modified from this question.
#Service
public class MyBeanService{
#Autowired
CustomObject customObj; // no arguments to constructor
#Autowired
MyConstructorClass myConstructorClass; // requires `customObj` as an argument
....
}
How can I modify MyBeanService to properly construct myConstructorClass with customObj?
You just need to annotated the constructor of MyConstructorClass with #Autowired:
#Component
public class MyConstructorClass {
final private CustomObject customObj;
#Autowired
public MyConstructorClass(CustomObject customObj) {
this.customObj = customObj;
}
}
Another alternative, (without adding the #Autowired constructor to MyConstructorClass) is to use a #Configuration bean:
#Configuration
public class MyConfiguration {
#Bean
public CustomObject customObj() {
return customObj;
}
#Bean
public MyConstructorClass myConstructorClass() {
return new MyConstructorClass(customObj());
}
#Bean
public MyBeanService myBeanService() {
return new MyBeanService();
}
}
you can use the <constructor-arg> in your servlet
<bean id="myConstructorClass" class="package.MyConstructorClass">
<constructor-arg>
<bean class="package.CustomObject"/>
</constructor-arg>
</bean>
If this is the only place you need to use that class could use #PostConstruct to instantiate itself. I think there is a better solution, but this is off the top of my head.
#Service
public class MyBeanService{
#Autowired
CustomObject customObj;
MyConstructorClass myConstructorClass;
#PostConstruct
public void construct()
{
myConstructorClass = new MyConstructorClass(customObj);
}
}
In the constructor, you can refer to other beans defined in Spring.
<bean id="myConstructorClass" class="package.MyConstructorClass">
<constructor-arg index="0" ref="customObj"/>
</bean>

Spring Test mock one dependency

Suppose I have these two parts of XML Spring config in two distinct files;
//daoContext.xml
<bean id="myDao" class="com.MyDao"/>
//logicContext.xml
<bean id="myLogic" class="com.MyLogic">
<constructor-arg ref="myDao"/><!--or other type of injection--?
</bean>
And there is the test class:
#ContextConfiguration("logicContext.xml")
public class BaseLogicTest extends AbstractTestNGSpringContextTests {
#Autowired
private MyLogic myLogic;
#Test
public void testMyTestable() {
//...
}
}
Now, what I want is to be able to mock MyDao class and inject is somehow into MyLogic which is to be injected in BaseLogicTest so I can use MyLogic with a mocked MyDao. Is this possible using Spring/Spring Test?
The simplest solution is load all your xml. And manually replace dependence in test case.
#ContextConfiguration("logicContext.xml")
public class BaseLogicTest extends AbstractTestNGSpringContextTests {
#Autowired
private MyLogic myLogic;
#Before
public void injectTestDoubles() {
myLogic.setMyDao(...);
}
#DirtiesContext
#Test ...//test methods
}
But this corrupts the application context, so you need #DirtiesContext if you need "real" myDao in other test case sharing the same application context.
The most popular solution (my personal opinion :P ) is using mockito and a test-specific xml.
//daoContext.xml
<bean id="myDao" class="com.MyDao"/>
//logicContext.xml
<bean id="myLogic" class="com.MyLogic">
<constructor-arg ref="myDao"/><!--or other type of injection--?
</bean>
//test-logicContext.xml
<bean id="myDao" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="com.MyDao" />
</bean>
#ContextConfiguration({"logicContext.xml", "test-logicContext.xml"})
public class BaseLogicTest extends AbstractTestNGSpringContextTests {
#Autowired
private MyLogic myLogic;
#Autowired
private MyDao myDao;//retrieve mock so you could define expectations
#Test //test methods
#After public void clearMocks() {
Mockito.reset(myDao);//this is important if you have several test methods
}
}
And this solution works for other mock framework like easyMock.
You can do this by creating a FactoryBean to create the MyDao (or any) mock to be injected into your MyLogic instance.
public class FactoryBeanForMocks<T> implements FactoryBean<T> {
private Class<T> mockClass;
public FactoryBeanForMocks(Class<T> mockClass) {
super();
this.mockClass = mockClass;
}
#Override
public T getObject() throws Exception {
return Mockito.mock(mockClass);
}
#Override
public Class<?> getObjectType() {
return mockClass;
}
#Override
public boolean isSingleton() {
return true;
}
}
Make the factory bean entry into your logicContext.xml so that a mock of MyDao can be injected into MyLogic:
//logicContext.xml
<bean id="myLogic" class="com.MyLogic">
<constructor-arg ref="myDao"/><!--or other type of injection--?
</bean>
<bean id="myDao" class="x.y.z.FactoryBeanForMocks">
<constructor-arg name="mockClass" value="x.y.MyDao"></constructor-arg>
</bean>
And this is your test class:
#ContextConfiguration("logicContext.xml")
public class BaseLogicTest extends AbstractTestNGSpringContextTests {
#Autowired
private MyLogic myLogic;
//You can inject the mock myDao into it so that you can stub/verify method calls on it
#Autowired
private MyDao myDao;
#Test
public void testMyTestable() {
//...
when(myDao.process()).thenReturn("a");//stubbing myDao.process()
assertEquals("a", myLogic.processRequest());// assuming myLogic.processRequest() calls myDao.process()
}
}

Categories

Resources