Spring - Autowire Service into POJO - java

I have a model in which I want to inject my service.
My Model
#Configurable
#Entity
#Table(name = "user")
public Class User {
#Autowired
private UserService userService;
{
System.out.println("Trying Service : " + userService.getMyName());
}
}
Here I get always a NullPointerException on 7'th line.
In my spring-context.xml I have :
<context:spring-configured/>
<bean
class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
<bean
class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" />
EDIT
UserService
#Component
public Class UserService {
public String getMyName() { return "it's Me!";}
}

Spring managed components can be wired only into another beans managed by Spring.
However, there is a trick to add service to your POJO if you really need it:
Add UserService as a static field to your POJO with a setter
In UserService after spring initializes the bean, set itself as a field on the POJO (this can be done in #PostConstruct method)

Make a static instance of UserService available:
#Service
public Class UserService {
private static UserService instance;
public static UserService getInstance() { return instance; }
#PostConstruct
void init() { instance = this; }
public String getMyName() { return "it's Me!";}
}
call with:
UserService.getInstance().getMyName()

Related

Intellij Idea Structural Replacement (replacing autowired annotation)

I wonder whether it's possible to replace all the Autowired fields with final ones and #RequiredArgsConstructor below the class declaration?
For instance, replace the following code
public class Controller {
#Autowired
private Reposiroty repository;
#Autowired
private Service service;
...
}
with something like that:
#RequiredArgsConstructor
public class Controller {
private final Reposiroty repository;
private final Service service;
...
}
Thanks in advance!

How provide a different bean implementation to #Autowire field based on annotation?

I have a config class that provides two implemenations of the same base bean interface. I want these to be set on the autowired fields conditionally based on an annotation on the field.
public class MyController
{
#Autowired
private MyBeanInterface base;
#Autowired
#MyAnnotation
private MyBeanInterface special;
}
This is a pesudo-code of the config class:
#Configuration
public class ConfigClass
{
#Bean
#Primary
public MyBeanInterface getNormalBeanInterface()
{
return new MyBeanInterfaceImpl();
}
#Bean
//This doesn't work
#ConditionalOnClass(MyAnnotation.class)
public MyBeanInterface getSpecialBeanInterface()
{
return new MyBeanInterfaceForMyAnnotation();
}
}
How can I make the annotated field be populated by the second bean?
Use Qualifier annotation. Example:
Controller:
Add Qualifier annotation at the injected fields with bean id as parameter:
public class MyController
{
#Autowired
#Qualifier("normalBean")
private MyBeanInterface base;
#Autowired
#Qualifier("specialBean")
private MyBeanInterface special;
}
ConfigClass
Specify bean id:
#Configuration
public class ConfigClass
{
#Bean(name="normalBean")
#Primary
public MyBeanInterface getNormalBeanInterface()
{
return new MyBeanInterfaceImpl();
}
#Bean(name="specialBean")
public MyBeanInterface getSpecialBeanInterface()
{
return new MyBeanInterfaceForMyAnnotation();
}
}

spring multiple transactionmanagers for similar datasources

I have two datasources that are equal in their structure but not in their Data.
My application has to deal with both of them at the same time.
I have controller, servie, dao structure that looks like this.
Controller Modell:
#Controller
public abstract class MyFancyControllerModell{
private MyService service;
public MyFancyControllerModell (MyService service){
this.service = service;
}
#RequestMapping(....)
public void editSomeData(String data){....}
}
Controller implementation:
#Controller
#RequestMapping(...)
public class MyControllerImpl1 extends MyFancyControllerModell{
#Autowired
public MyControllerImpl1(#Qualifier("myServiceInstance1") MyService service){
super(service);
}
}
#Controller
#RequestMapping(...)
public class MyControllerImpl2 extends MyFancyControllerModell{
#Autowired
public MyControllerImpl2(#Qualifier("myServiceInstance2") MyService service){
super(service);
}
}
And the Service:
public class MyService{
private MyDao myDao;
public MyService(MyDao myDao){
this.myDao = myDao;
}
#Transactional
public void editSomeData(String data){...}
}
I create the Beans in my configuration class like this:
private DataSource lookupDataSource(final String jndiName) {
final JndiDataSourceLookup dsLookup = new JndiDataSourceLookup();
dsLookup.setResourceRef(true);
return dsLookup.getDataSource(jndiName);
}
#Bean
public DataSource dataSource1(){
return lookUpDataSource("dataSource1");
}
#Bean
public DataSource dataSource2(){
return lookUpDataSource("dataSource2");
}
#Bean
public MyService myServiceInstance1(#Qualifier("dataSource1") DataSource dataSource){
return new(MyService(new MyDao(dataSource))));
}
#Bean
public MyService myServiceInstance1(#Qualifier("dataSource1") DataSource dataSource){
return new(MyService(new MyDao(dataSource)));
}
My question is, is it possible to create transactionmanagers for both datasources without the need to declare in the service layer which transactionmanager is used?
I tried creating them as bean just like the services but that did not work.
Check out here the answers for previous quesion related to transaction manager...
https://stackoverflow.com/a/1961853/7504001

How to mock any services inside a #MockedBean?

Is it possible to just ignore/mock any injected dependencies inside a MockedBean?
Example:
#Service
public class MyService {
#Autowired
private MailerService mailer;
public void test1() {
//does not use mailer
}
public void test2() {
//...
mailer.send();
}
}
#Service
public class MailerService {
//I want these to be automatically mocked without explicit declaration
#Autowired
private JavaMailSender sender;
#Autowired
private SomeMoreService more;
//also these should be mocked without having to provide properties
#Value("${host}") private String host;
#Value("${user}") private String user;
#Value("${pass}") private String pass;
}
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest
public class MyServiceTest {
#Autowird
private MyService myservice;
#MockBean
private MailserService mailer;
#Test
public void test1() {
myservice.test1();
}
}
I could use #MockBean to sort out mailer injection dependency. But any service inside the mocked bean would also have to be explicitly mocked.
Question: is it possible to mock a service "away". Means, just mock the bean and don't care what's inside the #MockedBean (or automatically also mock anything inside #MockedBean)?
As for me the best way to inject mocks is to use MockitoJUnitRunner
#RunWith(MockitoJUnitRunner.class)
public class MocksTests {
#InjectMocks
private ParentService parent;
#Mock
private InnerService inner; // this will be injected into parent
//your tests
}

How can I use a DAO inside a Controller in Spring MVC?

In a Spring MVC project I've a DAO class myproj.models.UserDAO:
#Repository
#Transactional
public class UserDAO {
// UserDAO methods ...
}
and I should use it inside a controller, say myproj.controllers.UserController:
#Controller
public class UserController {
// UserController methods ...
#RequestMapping(value="/{user}")
public String create(String user) {
// Here I want to use the UserDAO
// ...
}
}
How can I create an instance of the UserDAO object and use it inside a controller method?
You could try following
#Repository
#Transactional
public class UserDAO {
// UserDAO methods ...
}
Controller:
#Controller
public class UserController {
#Autowired //this will give you the reference to UserDAO
UserDAO userDao;
// UserController methods ...
#RequestMapping(value="/{user}")
public String create(String user) {
// Here I want to use the UserDAO
userDao.userDaoMethod();
// ...
}
}
For more information on #Autowired explore this
User Autowired annotation to inject a bean instance of your DAO:
#Controller
public class UserController {
#Autowired
UserDAO userDao;
#RequestMapping(value="/{user}")
public String create(String user) {
userDao.method();
}
}

Categories