Как решить NullPointerException, когда компонент Autowiring в приложении весенней загрузки - PullRequest
0 голосов
/ 12 июня 2019

При автоматическом подключении компонента, в данном случае @Service, я получаю исключение BeanInstantiationException из NullPointerException.

Я использую создание bean-компонентов на основе аннотаций, насколько я понимаю, все, что нужно, это аннотировать класс с помощью @Service, @Repository, @Component или @Controller. Я пробовал сканировать пакеты и классы по отдельности и в сочетании, и использую @EnableJpaRepositories в пакете репозитория.

Заявка:

package com.demoApp;


import com.demoApp.backend.DAOs.UserDAO;
import com.demoApp.backend.domain.User;
import com.demoApp.backend.services.Services;
import com.demoApp.ui.views.MainView;
import com.demoApp.app.security.SecurityConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

/**
 * Spring boot web application initializer.
 */
@SpringBootApplication(scanBasePackageClasses = { SecurityConfiguration.class, MainView.class, admexFront.class,
        UserDAO.class, Services.class}, exclude = ErrorMvcAutoConfiguration.class,scanBasePackages = {"com.demoApp.backend.services"})
@EnableJpaRepositories(basePackages = {"com.demoApp.backend.DAOs"})
@EntityScan(basePackages = {"com.demoApp.backend.domain"})
public class admexFront extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(admexFront.class, args);
    }

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(admexFront.class);
    }
}

А вот класс вспомогательных услуг:

package com.demoApp.backend.services;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.web.context.annotation.SessionScope;

import java.io.Serializable;

@Service(value = "Services")
@SessionScope
public class Services implements Serializable {

    @Autowired
    private ApplicationContext applicationContext;

    public ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    public ContactService getContactService() {
        return applicationContext.getBean(ContactService.class);
    }

    public UserService getUserService() {
        return applicationContext.getBean(UserService.class);
    }
}

Вот маршрут ContactView, в котором происходит ошибка:

package com.demoApp.ui.views;

import com.demoApp.app.security.SecurityUtils;
import com.demoApp.backend.domain.Client;
import com.demoApp.backend.domain.Contact;
import com.demoApp.backend.domain.User;
import com.demoApp.backend.services.Services;
import com.vaadin.flow.component.Tag;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.Route;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;

@Tag("contact-view")
@Route(value = "contacts", layout = MenuBar.class)
public class ContactView extends Div {


    public static String NAME = "Contacts";
    public static String ROUTE = "contacts";
    public static String ICON = "arrow-right";

    private VerticalLayout mainLayout = new VerticalLayout();

    @Autowired
    private Services services;

    @Autowired
    public ContactView() {
        User loggedInUser = SecurityUtils.getUser();

        Contact userContact = loggedInUser.getContactRef();
        Client client = userContact.getClientRef();


        mainLayout.setDefaultHorizontalComponentAlignment(FlexComponent.Alignment.AUTO);
        add(mainLayout);


        List<Contact> contacts = services.getContactService().getAllContactsFromClient(client);

        Grid<Contact> contactGrid = new Grid<>(Contact.class);
        contactGrid.setColumns("Contact Code", "Name", "Email");

        add(contactGrid);

    }
}

Я получаю сообщение об ошибке:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.demoApp.ui.views.ContactView': Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [co
m.demoApp.ui.views.ContactView]: Constructor threw exception; nested exception is java.lang.NullPointerException

1 Ответ

1 голос
/ 12 июня 2019

Поставь себя на место Spring. Он должен создать ContactView и заполнить его services поле.

Чтобы иметь возможность заполнять поле объекта, объект должен существовать, верно? Таким образом, он должен вызвать конструктор для создания объекта, до того, как сможет установить его поле. Таким образом, когда вызывается конструктор, поле еще не может быть заполнено и, таким образом, является нулевым. Отсюда NullPointerException, так как вы вызываете метод для поля внутри конструктора.

Решение: не используйте полевую инъекцию. Используйте конструктор инъекций.

// NO @Autowired here
private Services services;

@Autowired // this is actually optional unless you have another constructor
public ContactView(Services services) {
    this.services = services;
    // ...
...