Search code examples
spring-bootvaadinautowiredvaadin-flow

Vaadin Spring Boot @autowired field returns null in a view


First off, please excuse my question due to my being new to spring boot ecosystem. In my application, I've a vaadin page, where I want to submit user details to DB, using repository. In my view class, I've added them as @autowired fields, however, during the runtime, I see that their values are run so the operation fails. I know that to benefit from @autowired, the instances should not be created newly during constructing but I couldn't figure out how I should do it on my own. Here are my classes:

@SuppressWarnings("serial")
public class LoginAwareComposite extends Composite<Div> {

@Autowired
private ApplicationEventPublisher publisher;

public LoginAwareComposite() {
}

@Override
protected void onAttach(AttachEvent event) {
    super.onAttach(event);
    UserCredentials userPrincipal = UI.getCurrent().getSession().getAttribute(UserCredentials.class);

    if (userPrincipal != null) {
        // --- NOT LOGGED IN
        UI.getCurrent().navigate(AddressBookManagementView.class);
    } 

}

}

@SuppressWarnings("serial")
@Route(value = "account")
@Theme(value = Lumo.class, variant = Lumo.LIGHT)
public class AddressBookManagementView extends LoginAwareComposite {

private VerticalLayout pageLayout = new VerticalLayout();

public AddressBookManagementView() {
    getContent().setSizeFull();
    getContent().add(initPage());

}

private Component initPage() {
    pageLayout.getStyle().set("padding-left", "0px");
    pageLayout.getStyle().set("padding-bottom", "0px");
    pageLayout.getStyle().set("padding-right", "0px");
    pageLayout.getStyle().set("overflow", "auto");
    pageLayout.setSizeFull();

    pageLayout.add(new HeaderLayout(), new BodyLayout(), new FooterLayout());

    return pageLayout;
}

}

@SuppressWarnings("serial")
@SpringComponent
public class BodyLayout extends VerticalLayout {

// some fields

@Autowired
EmailRepository emailRepository;

@Autowired
FaxRepository faxRepository;

public BodyLayout() {
    init(); //this function inits the view, and eventually inits the on click event for submit button , which then calls my function
}

private void myFunction() {
//here i use the repository entities but they do return null although they are autowired
}

So what happens is, in BodyLayout's constructor we call init() function which is used to init the layout and give functionality buttons etc, one of subfunctions inside the init method gives functionality to submit button using myFunction. MyFuction uses the repository entity but it returns null.


Solution

  • I was able to get it working as follows:

    @SuppressWarnings("serial")
    @Route(value = "account")
    @Theme(value = Lumo.class, variant = Lumo.LIGHT)
    @UIScope
    @SpringComponent
    public class AddressBookManagementView extends LoginAwareComposite {
    
    private VerticalLayout pageLayout = new VerticalLayout();
    
    @Autowired
    BodyLayout bodyLayout;
    
    public AddressBookManagementView(BodyLayout bodyLayout) {
        this.bodyLayout = bodyLayout;
        getContent().setSizeFull();
        getContent().add(initPage());
    
    }
    
    private Component initPage() {
        pageLayout.getStyle().set("padding-left", "0px");
        pageLayout.getStyle().set("padding-bottom", "0px");
        pageLayout.getStyle().set("padding-right", "0px");
        pageLayout.getStyle().set("overflow", "auto");
        pageLayout.setSizeFull();
    
        pageLayout.add(new HeaderLayout(), bodyLayout, new FooterLayout());
    
        return pageLayout;
    }
    

    Then BodyLayout is

    @SuppressWarnings("serial")
    @UIScope
    @SpringComponent
    public class BodyLayout extends VerticalLayout {
    
    private final EmailRepository emailRepository;
    
    private final FaxRepository faxRepository;
    
    @Autowired
    public BodyLayout(EmailRepository emailRepository, FaxRepository faxRepository) {
        this.emailRepository = emailRepository;
        this.faxRepository = faxRepository;
        init();
    }