Spring Boot wywołanie metody z serwisu NullPointer

0

Cześć.

W swojej klasie @Service odpowiadającą za aktualizację bazy, mam zaimplementowaną metodę update(), która ma być uruchamiana w momencie gdy klasa przechowująca kolekcję zmieni swój stan(dokładnie czy pojawią się w niej nowe wyniki).

Problem jest taki, że nie wiem w jaki sposób z poziomu zwykłej klasy, mogę odwołać się do metody update() z serwisu, aby nie uzyskać NullPointera.

Czy w ogóle odwoływanie się bezpośrednio do serwisu nie jest błędem ?

0

Przeciez klasa ozaczona @Service, @Component czy jakkolwiek inaczej to nadal zwykła klasa, odwołujesz się do niej jak do każdej innej. Z tym, że siedzi już ona w kontenerze Springa, więc możesz ją po prostu wstrzyknąć do swojej klasy i wywołać na niej te metodę update, jezeli leci jakiś NullPointer to po prostu coś źle napisałeś/skonfigurowałeś.

Ewentualnie, jeżeli nie chcesz bezpośrednio wywoływać tej metody, możesz poczytać o czymś takim jak Observer Pattern.

0

Pokaż kod.

0

Pokaż kod bo ciężko wróżyć z niczego.
Jak kolega wyżej wspomniał, jesteś pewien, że masz @Autowired / @Inject gdzieś w swojej klasie (na konstruktorze przyjmującym service, setterze serwisu czy chociażby polu klasy), w której używasz tego serwisu?

0

Tak jak koledzy wyżej pisali, najlepiej byłoby zobaczyć kod ale jeśli go jeszcze nie wrzuciłeś to obstawiam że sytuacja wygląda tak że wstrzykujesz jakąś instancję w zwykłej klasie (taka która nie jest zarządzana przez springa) i dlatego dostajesz tam nulla.
Tworzenie beanów w klasyczny sposób przez new jest głupim rozwiązaniem bo sam prosisz się o kuku... Weżmy np. kod:

@Controller
public class Controller {
  @GetMapping("/example")
  public String example() {
    MyService my = new MyService();
    my.doStuff();
  }
}

@Service
public class MyService {

  @Autowired
  MyRepository repo;

  public void doStuff() {
    repo.findByName( "steve" );
  }
}

@Repository
public interface MyRepository extends CrudRepository<My, Long> {

  List<My> findByName( String name );
}

MyService oczywiście zostanie utworzony ale repo które jest u niego wstrzykiwane już nie więc NPE i tak poleci tylko dalej. Chyba że wstrzykujesz przez konstruktor to wówczas tworząc przez new będziesz zmuszony coś tam podstawić, natomiast moim zdaniem nadal nie widzę sensu robienia z klasy bean'a a potem ręcznie ją tworzyć.

0

Jak wrócę z pracy to podeślę kod, jak uda mi się dodać Observer Pattern:) Wczoraj niestety cały dzień bez kompa.

0

MyService w klasie Controller tworzysz poprzez new, wiec czego oczekujesz?
Uzyj do tego @Autowired jak jak to robisz z **MyRepository **w MyService, albo jeszcze lepiej, wywal @Autowired i uzyj konstruktorow do wstrzykiwania zaleznosci, a pola zadeklaruj jako private final

0

Dobra Kod poniżej, działa nie wywala błędu, ale czy to jest czysto i poprawnie ? Najbardziej mi się nie podobają implementacje list.

@Service
public class ApiFootballService implements Observer {

    private final ApiFootballFacade apiFootballFacade;
    private final ApiFootballGameCollection apiFootballGameCollection;

    @Autowired
    public ApiFootballService(ApiFootballFacade apiFootballFacade, ApiFootballGameCollection apiFootballGameCollection) {
        this.apiFootballFacade = apiFootballFacade;
        this.apiFootballGameCollection = apiFootballGameCollection;
        apiFootballGameCollection.register(this);
    }

    @Scheduled(cron = "*/30 * * * * *")
    public void updateCollectionGame(){
        apiFootballFacade.updateGameCollection();
    }

    @Override
    public void update() {
        System.out.println("Nowe ukończone mecze");
    }
}

@Component
public class ApiFootballFacade {

    private final ApiFootballGameCollection apiFootballGameCollection;

    @Autowired
    public ApiFootballFacade(ApiFootballGameCollection apiFootballGameCollection) {
        this.apiFootballGameCollection=apiFootballGameCollection;
    }

    private final ApiFootballUrls apiFootballUrls = new ApiFootballUrls();
    private final ApiFootballPojo apiFootballPojo = new ApiFootballPojo();
    private final ApiFootballFilter apiFootballFilter = new ApiFootballFilter();

    public void updateGameCollection(){
       List<String> urls =  apiFootballUrls.createUrl();
       List<Game> games = apiFootballPojo.getGameEntityCollection(urls);
       System.out.println(apiFootballFilter.getFinishedGames(games).size());
       apiFootballGameCollection.setFinishedGames(apiFootballFilter.getFinishedGames(games));
       apiFootballGameCollection.setAllGames(apiFootballFilter.getAllGames(games));
    }
}

@Getter
@Setter
@Component
public class ApiFootballGameCollection implements Observable{

    private List<Observer> observerList = new ArrayList<>();;
    private List<Game> finishedGames = new ArrayList<>();
    private List<Game> allGames = new ArrayList<>();


    public void setFinishedGames(List<Game> finishedGames) {
        this.finishedGames = finishedGames;
        notifyObserver();
    }

    @Override
    public void register(Observer observer) {
        observerList.add(observer);
    }

    @Override
    public void unregister(Observer observer) {
        observerList.remove(observer);
    }

    @Override
    public void notifyObserver() {
        for(Observer o: observerList){
            o.update();
        }
    }
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1