In the first case the autowired cartService works fine, but I don't know why in the second case when I want to use the autowired cartService(in an another class) I get null as its value.
Here is a part of the source:
Repository:
#Repository
public interface CartRepository extends JpaRepository<Cart, Integer> {
Cart findById(int id);
}
Service:
public interface CartService{
Iterable<Cart> getAllCart();
Cart getCart(int id);
void save(Cart cart);
}
Service Implementation:
#Service
public class CartServiceImpl implements CartService{
#Autowired
CartRepository cartRepository;
#Override
public Iterable<Cart> getAllCart() {
return cartRepository.findAll();
}
#Override
public Cart getCart(int id) {
return cartRepository.findById(id);
}
#Override
public void save(Cart cart) {
cartRepository.saveAndFlush(cart);
}
}
#Component
public class ColumnLay extends VerticalLayout {
#Autowired
CartService cartService;
//...some code...cartService works fine
}
UI class
#Route("purchase")
#Component
#UIScope
public class Purchase extends VerticalLayout {
#Autowired
CartService cartService;
//here when I use cartService I get null
//some code goes here
}
You did not show where in the Purchase class you happen to get a NullPointerException, but I suspect that it happens in the constructor, because that would make perfect sense.
Autowiring happens after the construction of an object. Therefore, your autowired cartService is null in your constructor. If there is a method annotated with #PostConstruct, then this is called after the autowiring - your service will be there then.
Or you could switch from field injection to constructor injection. By using constructor injection, the cartService will be available in the constructor already.
#Route("purchase")
#Component
#UIScope
public class Purchase extends VerticalLayout {
// no annotation here!
CartService cartService;
//this way cartService is not null in constructor
#Autowired
public Purchase(CartService cartService){
this.cartService = cartService;
}
}
Related
I have the following class for a resource in my Spring Application
#RestController
#RequestMapping("/whatever")
public class SomeResource {
#Autowired
private CoolService coolService;
#RequestMapping(
path = "",
method = RequestMethod.GET)
#PreAuthorize("hasPerm(#coolService.resolve(#attribute))")
public void resource(#PathVariable("attribute") int attribute) {
...
}
And I want to call the bean implementing CoolService that has been autowired by the Spring context, because for CoolService I have two beans that get activated depending on the profile at startup.
public interface CoolService {
resolve(int attribute);
}
#Service
#Profile("super")
public interface SuperCoolService implements CoolService {
public Object resolve(int attribute){...}
}
#Service
#Profile("ultra")
public interface UltraCoolService implements CoolService {
public Object resolve(int attribute){...}
}
However it seems that Spring does not know which bean to use because there is no single bean just named CoolService, and inside the Preauthorize I can't write #superCoolService or #ultraCoolService because it is profile-dependant.
How can I achieve this?
If you want to define 2 bean implement same interface, then you can user annotation #Qualifier.
For example:
#Service
#Qualifier("service1")
public interface SuperCoolService implements CoolService {
public Object resolve(int attribute){...}
}
#Service
#Qualifier("service1")
public interface UltraCoolService implements CoolService {
public Object resolve(int attribute){...}
}
I followed the reference guide for creating and customizing Repositories and came up with the following:
public interface UserRepository extends JpaRepository<User, Long>, UserRepositoryCustom {
}
#Transactional(readOnly = true)
public class UserRepositoryCustomImpl implements UserRepositoryCustom {
#Override
public User findByToken(UUID token) {
return new User();
}
}
public interface UserRepositoryCustom {
User findByToken(UUID token);
}
In my case userRepository.findByToken(token);returns null.
#Edit
The test below fails
#RunWith(SpringRunner.class)
#DataJpaTest
#AutoConfigureTestDatabase(replace = NONE)
public class UserRepositoryTest {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
#Autowired
private TestEntityManager entityManager;
#Autowired
private UserRepository userRepository;
#Test
public void test() throws Exception{
assertNotNull(userRepository.findByToken(UUID.randomUUID()));
}
}
Your custom implementation is named wrong. It should be named after the class name of the Repository, not after the interface declaring the custom method.
Just renamed UserRepositoryCustomImpl to UserRepositoryImpl
The reason the method currently returns null is because Spring Data creates a query from the name and doesn't find a User with the specified token.
I have a base abstract controller class that contains a generic functionality. I also have a set of subclasses.
The abstract class has a property that i would like to Dependency inject. This property is common to all subclasses therefore i don't want it to be set on all the subclasses. but when I call abstract controller's function in subclass ,it turns out to be the property in abstract controller is null. I want to know why and how to fix it.Below is the code snippet:
Abstract Controller:
#Controller
public abstract class WebAPIBaseController {
#Resource
private IPermissionService permissionService;
public void validPermission(int user,String code){
permissionService.valid(user,code);
}
}
SubController
#Controller
#RequestMapping("/order")
public class OrderController extends WebAPIBaseController {
public String XXX(){
validPermission(1,"code");//it will throw a NullPointerException
}
}
besides,if I remove abstract controller(like below example) , it works good.
Remove abstract controller
#Controller
#RequestMapping("/order")
public class OrderController{
#Resource
private IPermissionService permissionService;
public void validPermission(int user,String code){
permissionService.valid(user,code);
}
public String XXX(){
validPermission(1,"code");//it works good
}
}
I don't think you need to inject the permissionService in the subclass, doing this you are hiding that of the superclass.
Have a look at this thread Spring can you autowire inside an abstract class? . You'll also find two other threads in one of the replies about this topic.
You could use #Autowired over the subclass constructor:
public abstract class WebAPIBaseController {
private final IPermissionService permissionService;
public WebAPIBaseController(IPermissionService permissionService) {
this.permissionService = permissionService;
}
public void validPermission(int user, String code){
permissionService.valid(user,code);
}
}
#Controller
#RequestMapping("/order")
public class OrderController extends WebAPIBaseController {
#Autowired
public OrderController(IPermissionService permissionService) {
super(permissionService);
}
public String XXX(){
validPermission(1,"code");//it will throw a NullPointerException
}
}
I want to read data in ApplicationListener, but my object is not initialized. Below is my code:
AppContextListener.java
#Component
public class AppContextListener implements ApplicationListener<ContextRefreshedEvent> {
#Override
public void onApplicationEvent(ContextRefreshedEvent event) {
AppContext.getInstance();
}
}
AppContext.java
public class AppContext {
private static AppContext instance;
#Autowired
MyElasticsearchRepository repository;
public AppContext(){
InitData();
}
public static synchronized AppContext getInstance() {
if (instance == null) {
instance = new AppContext();
}
return instance;
}
private void InitData(){
List<MyEntity> dataList = repository.findAllEntities();//repository is null here
//.......
}
}
MyElasticsearchRepository.java
public interface MyElasticsearchRepository extends ElasticsearchRepository<MyEntity,String>
{ }
problem
As you can see in my code, at InitData(), repository is null. I don't
know why #Autowired MyElasticsearchRepository repository; does not
worked here.
Please show me how to fix this. Thank you very much.
There are a couple of things wrong with your code.
First you are using the singleton pattern which I would say is an anti-pattern especially when combined with auto wiring.
Second in your getInstance() method you are creating a new instance of AppContext yourself. This instance isn't managed by Spring so #Autowired is pretty much useless here, Spring is only able to inject dependencies into beans it knows about.
Instead make your AppContext a component (or service what ever you like). Remove the getInstance method and use constructor injection instead.
#Component
public class AppContext {
private final MyElasticsearchRepository repository;
#Autowired
public AppContext(MyElasticsearchRepository repository){
this.repository=repository;
}
...
}
Thirdly you are trying to use the #Autowired instance from the constructor (you are doing method call which expects it to be there), however auto wiring can only be done on an instance of a bean. So at that moment the auto wiring hasn't taken place and your variable will always be null. Instead of calling the method from the constructor either, use constructor inject or annotate the InitData method with #PostConstruct.
#PostConstruct
private void InitData(){
List<MyEntity> dataList = repository.findAllEntities();
...
}
Now that your AppContext is a component it will be detect by spring and you can simply inject it into your ApplicationListener.
#Component
public class AppContextListener implements ApplicationListener<ContextRefreshedEvent> {
private final AppContext appContext;
#Autowired
public AppContextListener(AppContext appContext) {
this.appContext=appContext;
}
#Override
public void onApplicationEvent(ContextRefreshedEvent event) {
// Do your thing with appContext
}
}
Note: I prefer constructor injection for required fields and setter injection for optional fields. You should avoid field injection (i.e. #Autowired on instance fields) as that is considered a bad practice. See here why field injection is evil and should be avoided.
#Autowired will only work if bean is marked with Stereotype annotation (What's the difference between #Component, #Repository & #Service annotations in Spring?) or you explicitly define it in spring configuration.
AppContextListener.java
#Component // AFAIR not needed. Spring will create this bean when it will see that class implements `ApplicationListener` interface.
public class AppContextListener implements ApplicationListener<ContextRefreshedEvent> {
#Autowired
private AppContext appContext;
#Override
public void onApplicationEvent(ContextRefreshedEvent event) {
appContext.initData();
}
}
AppContext.java
#Component
public class AppContext {
#Autowired
MyElasticsearchRepository repository;
public void initData(){
List<MyEntity> dataList = repository.findAllEntities();//repository is null here
//.......
}
}
#Autowired will work only after AppContext object constructed. Since you try to access #Autowired element inside constructor, it doesn't exist.
Can't you just do this?
#Component
public class AppContextListener implements ApplicationListener<ContextRefreshedEvent> {
#Override
public void onApplicationEvent(ContextRefreshedEvent event) {
ApplicantContext context = event.getApplicationContext();
MyElasticsearchRepository repository = context.getBean(MyElasticSearchRepository.class);
//do stuff
}
}
http://docs.spring.io/autorepo/docs/spring/4.1.4.RELEASE/javadoc-api/org/springframework/context/event/ContextRefreshedEvent.html
So I have a number of generics in Spring 3.2 and ideally my architecture would look something like this.
class GenericDao<T>{}
class GenericService<T, T_DAO extends GenericDao<T>>
{
// FAILS
#Autowired
T_DAO;
}
#Component
class Foo{}
#Repository
class FooDao extends GenericDao<Foo>{}
#Service
FooService extends GenericService<Foo, FooDao>{}
Unfortunately with multiple implementations of the generics the autowiring throws an error about multiple matching bean definitions. I assume this is because #Autowired processes before type erasure. Every solution I've found or come up with looks ugly to me or just inexplicably refuses to work. What is the best way around this problem?
How about adding a constructor to the GenericService and move the autowiring to the extending class, e.g.
class GenericService<T, T_DAO extends GenericDao<T>> {
private final T_DAO tDao;
GenericService(T_DAO tDao) {
this.tDao = tDao;
}
}
#Service
FooService extends GenericService<Foo, FooDao> {
#Autowired
FooService(FooDao fooDao) {
super(fooDao);
}
}
Update:
As of Spring 4.0 RC1, it is possible to autowire based on generic type, which means that you can write a generic service like
class GenericService<T, T_DAO extends GenericDao<T>> {
#Autowired
private T_DAO tDao;
}
and create multiple different Spring beans of it like:
#Service
class FooService extends GenericService<Foo, FooDao> {
}
Here is a closest solution. The specialized DAOs are annotated at the business layer. As in the question from OP, the best effort would be having an annotated DAO in the EntityDAO generic template itself. Type erasure seems to be not allowing the specialized type information to get passed onto the spring factories [resulting in reporting matching beans from all the specialized DAOs]
The Generic Entity DAO template
public class EntityDAO<T>
{
#Autowired
SessionFactory factory;
public Session getCurrentSession()
{
return factory.getCurrentSession();
}
public void create(T record)
{
getCurrentSession().save(record);
}
public void update(T record)
{
getCurrentSession().update(record);
}
public void delete(T record)
{
getCurrentSession().delete(record);
}
public void persist(T record)
{
getCurrentSession().saveOrUpdate(record);
}
public T get(Class<T> clazz, Integer id)
{
return (T) getCurrentSession().get(clazz, id);
}
}
The Generic Entity Based Business Layer Template
public abstract class EntityBusinessService<T>
implements Serializable
{
public abstract EntityDAO<T> getDAO();
//Rest of code.
}
An Example Specialized Entity DAO
#Transactional
#Repository
public class UserDAO
extends EntityDAO<User>
{
}
An Example Specialized Entity Business Class
#Transactional
#Service
#Scope("prototype")
public class UserBusinessService
extends EntityBusinessService<User>
{
#Autowired
UserDAO dao;
#Override
public EntityDAO<User> getDAO()
{
return dao;
}
//Rest of code
}
You can remove the #autowire annotation and perform delayed “autowire” using #PostConstruct and ServiceLocatorFactoryBean.
Your GenericService will look similar to this
public class GenericService<T, T_DAO extends GenericDao<T>>{
#Autowired
private DaoLocator daoLocatorFactoryBean;
//No need to autowried, autowireDao() will do this for you
T_DAO dao;
#SuppressWarnings("unchecked")
#PostConstruct
protected void autowireDao(){
//Read the actual class at run time
final Type type;
type = ((ParameterizedType) getClass().getGenericSuperclass())
.getActualTypeArguments()[1];
//figure out the class of the fully qualified class name
//this way you can know the bean name to look for
final String typeClass = type.toString();
String daoName = typeClass.substring(typeClass.lastIndexOf('.')+1
,typeClass.length());
daoName = Character.toLowerCase(daoName.charAt(0)) + daoName.substring(1);
this.dao = (T_DAO) daoLocatorFactoryBean.lookup(daoName);
}
daoLocatorFactoryBean does the magic for you.
In order to use it you need to add an interface similar to the one below:
public interface DaoLocator {
public GenericDao<?> lookup(String serviceName);
}
You need to add the following snippet to your applicationContext.xml
<bean id="daoLocatorFactoryBean"
class="org.springframework.beans.factory.config.ServiceLocatorFactoryBean">
<property name="serviceLocatorInterface"
value="org.haim.springframwork.stackoverflow.DaoLocator" />
</bean>
This is a nice trick and it will save you little boilerplate classes.
B.T.W I do not see this boilerplate code as a big issue and the project I working for uses matsev approach.
Why do you want a generic service ? Service classes are meant for specific units of work involving multple entities. You can just inject a repository straight into a controller.
Here is an example of generic repository with constructor argument, you could also make each method Generic instead and have no constructor argument. But each method call would require class as parameter:
public class DomainRepository<T> {
#Resource(name = "sessionFactory")
protected SessionFactory sessionFactory;
public DomainRepository(Class genericType) {
this.genericType = genericType;
}
#Transactional(readOnly = true)
public T get(final long id) {
return (T) sessionFactory.getCurrentSession().get(genericType, id);
}
Example of bean definition for the generic repository - you could have multple different beans, using different contstructor args.
<bean id="tagRepository" class="com.yourcompnay.data.DomainRepository">
<constructor-arg value="com.yourcompnay.domain.Tag"/>
</bean>
Depdncy injection of bean using resource annotation
#Resource(name = "tagRepository")
private DomainRepository<Tag> tagRepository;
And this allows the Domainreposiroty to be subclassed for specific entities/methods, which woul dallow autowiring :
public class PersonRepository extends DomainRepository<Person> {
public PersonRepository(){
super(Person.class);
}
...
You should use autowiring in classes which extends these generics
For this question one needs to understand about what autowire is. In common terms we can say that through autowire we create a object instance/bean at the time of deployment of the web app. So now going with the question if you are declaring autowiring in multiple places with the same name. Then this error comes. Autowiring can be done in multiple ways so if you are using multiple type of autowiring technique, then also one could get this error.
Complete Generic Solution using Spring 4:
Domain Class
#Component
class Foo{
}
#Component
class Bar{
}
DAO Layer
interface GenericDao<T>{
//list of methods
}
class GenericDaoImpl<T> implements GenericDao<T>{
#Autowired
SessionFactory factory;
private Class<T> domainClass; // Get Class Type of <T>
public Session getCurrentSession(){
return factory.getCurrentSession();
}
public DaoImpl() {
this.domainClass = (Class<T>) GenericTypeResolver.resolveTypeArgument(getClass(), DaoImpl.class);
}
//implementation of methods
}
interface FooDao extends GenericDao<Foo>{
//Define extra methods if required
}
interface BarDao extends GenericDao<Bar>{
//Define extra methods if required
}
#Repository
class FooDao extends GenericDaoImpl<Foo> implements FooDao{
//implementation of extra methods
}
#Repository
class BarDao extends GenericDaoImpl<Bar> implements BarDao{
//implementation of extra methods
}
Service Layer
interface GenericService<T>{
//List of methods
}
class GenericServiceImpl<T> implements GenericService<T>{
#Autowire
protected GenericDao<T> dao; //used to access DAO layer
}
class FooService extends GenericService<Foo>{
//Add extra methods of required
}
class BarService extends GenericService<Bar>{
//Add extra methods of required
}
#Service
class FooServiceImpl extends GenericServiceImpl<Foo> implements GenericService<Foo>{
//implementation of extra methods
}
#Service
class BarServiceImpl extends GenericServiceImpl<Bar> implements GenericService<Bar>{
//implementation of extra methods
}