Access method from different screen controller

Hello,

I’m attempting to set a SideMenu badge after an entity has been committed. This will update the number of entries that need to be addressed. I’ve extended the Main Screen and created a service to get the data from the database, and all works perfectly upon loading the application. The problem I’m running into is after I commit a new entry, I receive a Null Pointer Exception trying to update the badge from there, but I can’t find what the issue is.

FlightBadgeCountServiceBean.java

package com.company.badgecount.service;

import com.company.badgecount.entity.Flight;
import com.haulmont.cuba.core.EntityManager;
import com.haulmont.cuba.core.Persistence;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.inject.Inject;
import java.util.List;

@Service(FlightBadgeCountService.NAME)
@Transactional
public class FlightBadgeCountServiceBean implements FlightBadgeCountService {
    @Inject
    private Persistence persistence;

    private static final String GET_FLIGHTS = "select e from badgecount_Flight e where e.flightAcknowledged is null or e.flightAcknowledged = :flightAcknowledged";

    public Integer getUnacknowledgedFlights() {
        EntityManager em = persistence.getEntityManager();

        List<Flight> result = em.createQuery(GET_FLIGHTS, Flight.class).setParameter("flightAcknowledged", false).getResultList();

        return result.size();
    }
}

ExtMainScreen.java

package com.company.badgecount.web.screens;

import com.company.badgecount.service.FlightBadgeCountService;
import com.haulmont.cuba.gui.components.mainwindow.SideMenu;
import com.haulmont.cuba.gui.screen.Subscribe;
import com.haulmont.cuba.gui.screen.UiController;
import com.haulmont.cuba.gui.screen.UiDescriptor;
import com.haulmont.cuba.web.app.main.MainScreen;

import javax.inject.Inject;

@UiController("extMainScreen")
@UiDescriptor("ext-main-screen.xml")
public class ExtMainScreen extends MainScreen {
    @Inject
    private SideMenu sideMenu;
    @Inject
    private FlightBadgeCountService flightBadgeCountService;

    @Subscribe
    public void onInit(InitEvent event) {
        updateFlightBadgeCount();
    }

    public void updateFlightBadgeCount() {
        Integer flightCount = flightBadgeCountService.getUnacknowledgedFlights();

        if (flightCount != null && flightCount > 0) {
            sideMenu.getMenuItem("flightMenuItem").setBadgeText(flightCount.toString());
        }
    }



}

FlightEdit.java

package com.company.badgecount.web.screens.flight;

import com.company.badgecount.web.screens.ExtMainScreen;
import com.haulmont.cuba.gui.screen.*;
import com.company.badgecount.entity.Flight;

@UiController("badgecount_Flight.edit")
@UiDescriptor("flight-edit.xml")
@EditedEntityContainer("flightDc")
@LoadDataBeforeShow
public class FlightEdit extends StandardEditor<Flight> {

    @Subscribe
    public void onAfterCommitChanges(AfterCommitChangesEvent event) {
        ExtMainScreen extMainScreen = new ExtMainScreen();
        extMainScreen.updateFlightBadgeCount();
    }


}

So the problem seems to stem from the FlightEdit.java class in the onAfterCommitChanges event. Am I simply calling the ExtMainScreen controller incorrectly in this area? Is there a different way to accomplish this?

I’d love an idea of what I’m doing incorrectly.

Thanks,
Adam

I also referenced the following forum post, but I wasn’t able to get this working either.

Hi,

Please provide full exception stack trace. It is essential to understand the cause of your problem.

You cannot create screens like this, just by calling constructor.
If you are opening the screen, use Screens API to get instance of the screen controller:
https://doc.cuba-platform.com/manual-7.2/opening_screens.html

Well, I’m not really trying to create a new screen, but rather just trying to access the SideMenu that exists in the ext-main-screen.xml descriptor. I’m just trying to update the badge in this file once a Flight instance has been saved.

I created the service to do this because I needed a way to access the database to check the total count of Flights that qualify to be listed as the badge number. I don’t know of a good way to access the SideMenu outside of the ExtMainScreen.java controller.

However…

I found a solution from the PetClinic demo by creating a timer facet in the ext-main-screen.xml descriptor.

<facets>
    <timer id="refreshFlights" delay="3000" autostart="true" repeating="true"/>
</facets>

And then in the controller…

@Subscribe("refreshFlights")
public void onRefreshFlightsTimerAction(Timer.TimerActionEvent event) {
    updateFlightBadgeCount();
}

Thanks!
Adam

OK, the optimal recommended way to call logic from one screen to another is to use custom UI event.

  • create your own event class
  • throw event in FlightEdit
  • process event in ExtMainScreen

Examples here:
https://doc.cuba-platform.com/manual-7.2/events.html#ui_events

https://www.cuba-platform.com/guides/decouple-business-logic-with-app-events#cuba_ui_events