How to Lazy Load the #Named Bean - spring

I have a SessionScoped Named Bean as follows:
#Named("userBean")
#SessionScoped
public class UserBean implements Serializable {
.....
#PostConstruct
public void init()
{
...call some methods to fetch some data
}
Now the problem is, while deploying the application, init() will be called, and through-out the session it will not be called again.
My requirement is to make the init() call only when the bean is required to be initialized.
How can this be achieved?

#Named("userBean")
#SessionScoped
#Lazy
public class UserBean implements Serializable
And wherever you have #Autowired UserBean
make it
#Lazy
#Autowired
UserBean userbean;

Related

Spring Boot : How to access repository in java class #Autowired not working

Spring Boot : How to access repository in java class #Autowired not working
Please explain your solution with sample code as I am new to Spring Boot.
Repository
import java.util.List;
import org.springframework.data.repository.CrudRepository;
public interface StoreRepository extends CrudRepository<Store, Integer> {
List<Store> findAll();
}
Entity Store
import javax.persistence.Entity;
import javax.persistence.Id;
#Entity
public class Store {
#Id
private Integer sid;
private String sname;
public Store() {
}
public Store(Integer sid, String sname) {
super();
this.sid = sid;
this.sname = sname;
}
///GETTER and Setters here...
}
**Store Service **
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
#Service
public class StoreService {
#Autowired
private StoreRepository storeRepository;
public StoreService() {
}
public List<Stores> getAllStores(){
return (List<Stores>) storeRepository.findAll(); /* This works good. Through controller I can retrieve all data*/
}
}
Simple Java class
#Component
public class StoreWorker {
#Autowired
private StoreRepository storeRepository;
public StoreWorker() {
System.out.println(storeRepository.findAll()); /* Error */
}
Error :
Exception in thread "StoreWorker : restartedMain" java.lang.reflect.InvocationTargetException
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [io.store.workers.StoreWorker]: Constructor threw exception; nested exception is java.lang.NullPointerException
Caused by: java.lang.NullPointerException
Please explain your solution with sample code as I am new to Spring Boot.
You have to change your code in this way:
If you want to use your autowired bean in the constructor of your class, use constructor injection. This is also the most recommended way of injection.
#Component
public class StoreWorker {
private final StoreRepository storeRepository;
public StoreWorker(StoreRepository storeRepository) {
this.storeRepository = storeRepository;
System.out.println(storeRepository.findAll());
}
}
So when the StoreWorker gets instantiated the autowired bean storeRepository gets injected. Since this happens you are able to use storeRepository bean.
You should not put any logic in the constructor. Constructor methods are just to initialize your instance.
Make the call to the storeRepository in a separate method.
#Component
public class StoreWorker {
#Autowired
private StoreRepository storeRepository;
public void findAll() {
System.out.println(storeRepository.findAll());
}
}
When Spring is calling your constructor, the context is not fully initialized, and since you don't use constructor injection, storeRepository is not injected yet.
Constructor injection is the recommended way to inject by the Spring team. And as of Spring 4.3, you don't even need to add the #Autowired annotation on constructors.
#Component
public class StoreWorker {
private StoreRepository storeRepository;
//#Autowired not needed since v4.3
public StoreWorker(StoreRepository storeRepository) {
this.storeRepository = storeRepository;
}
...
}
If you want to do further initialization of your bean relying on other external beans, do it in a separate method annotated with #PostConstruct.
#Component
public class StoreWorker {
private StoreRepository storeRepository;
private List<Store> stores;
public StoreWorker(StoreRepository storeRepository) {
this.storeRepository = storeRepository;
}
#PostConstruct
public void initializeMyBean() {
stores = storeRepository.findAll();
}
}
You should use #Autowire in the constructor level in order to use Autowire variable inside the constructor.
#Component
public class StoreWorker {
#Autowired
public StoreWorker(StoreRepository storeRepository) {
System.out.println(storeRepository.findAll());
}
(or) Use PostConstruct
Autowiring happens after the construction of an object. Therefore they will not be set until after the constructor has completed.
If you need to run some initialization code, you should be able to pull the code in the constructor into a method and annotate that method with #PostConstruct.

Spring Boot - Autowired MongoClient

I got pretty confused now, I would like to use #Autowired MongoClient attribute in one of my Controller classes, but without success. The tricky part of it is that #Autowired is working from my #RestController.
#RestController
public final class WebController {
/** mongoClient */
#Autowired
private MongoClient mongoClient; <- here it's working ...
...
}
but:
#Controller
public final class MongoUsersDAO {
/** mongoClient */
#Autowired
private MongoClient mongoClient; <- not working ...
...
}
here I get null.
I do not think that the problem would be the component scan while my #SpringBootApplication is located at x.y.z, my #RestController at x.y.z.t and my #Controller at x.y.z.k packages, hence booth of them should be scanned by Spring.
(The Eclipse also marks my #Controller as a Spring class)
What else could be the problem then ?
Note:
If I add this to my #Controller it's working fine but the #Autowired still wount work:
#PostConstruct
public void init() {
System.out.println("INIT");
}
Note: In the mentioned MongoUsersDAO the autowired thing is not working at all, I've tried to get a simple property as well from the application.properties, without success.
Your problem occured because you have called new MongoUserDAO() inside your WebController class as you mentioned in the comment below your question. If you instantiate an object by hand and you have field annotated with #Autowired then this field won't be instantiated with expected instance.
Inject MongoUsersDAO directly to your WebController class as shown below, Spring will handle injecting MongoClient to MongoUserDAO class for you.
WebController :
#RestController
public final class WebController {
/** Service/Repository class*/
#Autowired
private MongoUsersDAO dao;
#GetMapping("/all")
public String getAll(){
dao.callSomeMethod();
}
}
MongoUsersDAO:
#Repository
public final class MongoUsersDAO {
/** mongoClient */
#Autowired
private MongoClient mongoClient;
...
}

spring auto-wire failed when inject a dependent bean into a #component java class

I have a Service class with #Component annotation, and this bean dependent a DAO like this:
#Component
public class CustomerService
{
#Setter
private CustomerDAO customerDAO;
}
and XML file goes like this:
<context:component-scan base-package="com.mkyong.customer" />
<bean id="customerDAO" class="com.mkyong.customer.dao.CustomerDAO" autowire="byName"></bean>
But, after the app is running, the field customerDAO can't been injected. If I replace #Setter with #Resource, that's will be fine. I deeply wonders, why the #Componet bean can't be injected with setter methods.
I'm using Spring 2.5.6;
In order to inject on setter, you will have to create a setter and annotate it with #Autowired.
#Component
public class CustomerService {
private CustomerDAO customerDAO;
#Autowired
public void setCustomerDAO(CustomerDAO customerDAO) {
this.customerDAO = customerDAO;
}
}

org.springframework.data.repository always null into custom UserDetailManager

In my project I've a DAO defined as a org.springframework.data.repository
#RepositoryRestResource(path = "/user")
public interface SymtUserDAO extends CrudRepository<User, Long>{
...
It works fine in controllers by #Autowired (Dependency Injection):
#Controller
public class ProveController {
#Autowired
private SymtUserDAO dao;
...
I need to use it in my custom UserDetailsManager but in here the dao is always null
public class SymtUserManager implements UserDetailsManager {
#Autowired
private SymtUserDAO dao;
I don't know if it matters but I instantiate my custom UserDetailManager in the AuthorizationServerConfigurerAdapter's constructor
/**
* This class is used to configure how our authorization server (the "/oauth/token" endpoint)
* validates client credentials.
*/
#Configuration
#EnableAuthorizationServer
#Order(Ordered.LOWEST_PRECEDENCE - 100)
protected static class OAuth2Config extends
AuthorizationServerConfigurerAdapter
{
....
public OAuth2Config() throws Exception {
UserDetailsService svc = new SymtUserManager(...
Why my working DAO (test passed in the controller) doesn't work ( it is always null) in the UserDetailsManager? what I have to do to use the DAO ( repository ) also into the UserDetailsManager?
EDIT: zeroflagL is right. I updated answer according to comments.
Your SymtUserManager is not s spring bean. Therefore it's not created and handeled by Spring bean container. Therefore spring can't inject dependency there.
You can autowire it into OAuth2Config constructor and pass it as constructor parameter to SymtUserManager:
#Configuration
#EnableAuthorizationServer
#Order(Ordered.LOWEST_PRECEDENCE - 100)
protected static class OAuth2Config extends
AuthorizationServerConfigurerAdapter
{
private SymtUserDAO dao;
#Autowire
public OAuth2Config(SymtUserDAO dao) throws Exception {
UserDetailsService svc = new SymtUserManager(dao, ...

management using MB #ViewScoped

//exemple01
#ManagedBean(name = "mb")
#ViewScoped
public class ExempleMB implements Serializable {
#ManagedProperty(value = "#{serviceBO}")
private ServiceBO serviceBO;
#PostConstruct
public void init{
list= serviceBO.list();
}
public void query(){
serviceBO.query(parameters);
}
}
Exemple 01:
Thus returns me the error
javax.faces.FacesException: java.io.NotSerializableException: being that it can not be serialized because he and managed by spring.
//exemple02
#ManagedBean(name = "mb")
#ViewScoped
public class ExempleMB implements Serializable {
#ManagedProperty(value = "#{serviceBO}")
private transient ServicoBO serviceBO;
#PostConstruct
public void init{
list= serviceBO.list();
}
public void query(){
servicoBO.query(paramestros);
}
}
Exemple 02:
He makes the query init, however the method this null search service, as it has to be marked as transient as this, how can I solve this problem.
Spring services are not serializable. You could instead inject fully serializable proxies, so that #ViewScoped bean serialization would happen flawlessly.
If you're using annotations, just add the following to your class definition:
#Service
#Scope(value = "singleton", proxyMode = ScopedProxyMode.INTERFACES)
public YourService { ... }
If you're using xml, do the following:
<bean id="yourService" class="your.package.YourServiceImpl" scope="singleton">
<aop:scoped-proxy proxy-target-class="false"/>
...
</bean>

Resources