Spring Boot, problem z implementacja metody

Spring Boot, problem z implementacja metody
BA
  • Rejestracja:około 6 lat
  • Ostatnio:ponad 4 lata
  • Postów:15
0

Potrzebuje lekkiej pomocy, probuje zrobic apke w springboocie, gre slownikowa, cos na zasadzie fiszek.
Podaje slowo po ang, odpowiadam po polsku. tak na start.
Powstal mi problem natury technicznej. Poki co, stworzylem tak, by wyswietlalo odpowiedz w konsoli.
Slowko wyskakuje mi po strone htmla, wpisuje odpowiedz, ktora sprawdza program i wyrzuca mi do konsoli czy dobrze czy zle.
Wszystko dziala, problem pojawil sie w momencie, gdy postanowielm przerzucic cala instrukcje warunkowa do innej klasy, w celu stworzenia metody.
tak by, getMappingu bylo czysciej. Niezaleznie jak robie, zawsze wywala mi nullpointerexception. probowalem na wiele sposob to obejsc, rowniez z try catchem.
siedze przy tym juz pare godzin i po prostu przestaje myslec, nic mi do glowy nowego nie przychodzi a efekt dalej zerowy. Problem pewnie trywialny, no ale coz...
Proby powyrzucalem z kodu by nie wprowadzac zamieszania.
W skrocie, chce wyrzucic wszystko z getmappingu do innej klasy( w tym PWord, EWord, count) tam wykonac wszystkie warunki i wrocic jedynie z odnosnikiem do metody, wstawiajac do modelmapy. Prosilbym o nakierowanie/ pokazanie zapisu krok po kroku, mam wrazenie, ze jakis step pomijam i wychodzi bagno.

Kopiuj
@Scope(value = "session")
@Controller
public class DictionaryController {

    private Random random = new Random();
    private User user = new User();

    private static String previousWord;

    @Autowired
    private LibraryRepository libraryRepository;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @GetMapping("/game")
    public String showEnglish(@RequestParam(required = false) String name, ModelMap modelMap) {

        long count = libraryRepository.count();
        int index = random.nextInt((int) count);

        String EWord = libraryRepository.findById(index).get().getEnglishWord();
        String PWord = libraryRepository.findById(index).get().getPolishWord();

        modelMap.put("englishW", EWord);
        modelMap.put("polishW", PWord);


        if (name != null) {

            if (previousWord.equals(name)) {
                System.out.println("dobrze");
            } else {
                System.out.println("zle");
            }
        }
        previousWord = PWord;
        return "game";
    }
}

E9
  • Rejestracja:ponad 8 lat
  • Ostatnio:5 dni
  • Postów:216
0

Nie napisałeś w którym miejscu leci ten nullpointer, nie wiemy też jak wyglądają klasy które tu wołasz.
Ale...

private static String previousWord;

previousWord.equals(name)

A po drodzę nie widzę by ten previousWord był stworzony. Jest do niego przypisane PWord ale dopiero po wywołaniu equals, czyli w pierwszej iteracji to rzuci wyjątkiem.

Poza tym, masz w tym kodzie parę WTFów, nie wiem czy wyciąłeś za dużo czy po prostu tak to wygląda...

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;

Pomijam fakt, że tego nigdzie nie używasz, ale w jakim celu masz to w kontrolerze?

 @Autowired
 private LibraryRepository libraryRepository;

wstrzykiwanie przez pole zamiast przez konstruktor

private User user = new User();

znów, tworzysz coś i nic z tym nie robisz

String EWord = libraryRepository.findById(index).get().getEnglishWord();

Optional pobrany przez get(), nie użyte ifPresent() albo chociaż isPresent()

Poza tym, logika "biznesowa" w kontrolerze? Nawet jak na taki mały projekt to IMO słaby pomysł.

edytowany 2x, ostatnio: Emdzej93
BA
  • Rejestracja:około 6 lat
  • Ostatnio:ponad 4 lata
  • Postów:15
0

previousWord jest stworzony na gorze jako static. w innym wypadku podmienia mi na kolejne wylosowane slowo. ( zakladamy, ze losowane slowo jest kluczem w mapie, my wpisujemy wartosc, tak by rownala sie wartosci z mapy przypisanej do klucza wyswietlanego). Co do tych kilku anomalii, ktorych nie uzywam, wyszedlem troche w przod z rzeczami, mam zamiar zliczac punkty itd, dlatego czesc rzeczy jest nieuzywana. Jestem osoba uczaca sie, wiec tez nie wykluczam bledow.
Co do libraryrepository. w repo mam podpietego hybernate z baza slow, nadawana w klasie library.

E9
  • Rejestracja:ponad 8 lat
  • Ostatnio:5 dni
  • Postów:216
0

Co z tego że jest jako static? Nie jest nigdzie zainicjalizowany. Robiąc equalsa robisz null.equals("value") co rzuca nullpointerem.

BA
  • Rejestracja:około 6 lat
  • Ostatnio:ponad 4 lata
  • Postów:15
0

akurat to wersja konsolowa, czyli dzialajaca

E9
  • Rejestracja:ponad 8 lat
  • Ostatnio:5 dni
  • Postów:216
0

Po pierwsze primo

Jestem osoba uczaca sie, wiec tez nie wykluczam bledow.

Mam nadzieje że nie odbierasz tego jako atak, ja po prostu starałem się wyłapać błędy które widać w Twoim kodzie, wyciągnąć wnioski, poprawić kod i na przyszłość nie pisać w ten sposób.

Po drugie primo

akurat to wersja konsolowa, czyli dzialajaca

Mam rozumieć, że masz gdzieś kod który nie działa, ale wysłałeś nam do weryfikacji wersje która działa i pytasz gdzie jest błąd w Twoim niedziałającym kodzie?...

Po trzecie primo, ultimo
Static nie oznacza że zmienna się sama zainicjalizuje

title

edytowany 2x, ostatnio: Emdzej93
BA
  • Rejestracja:około 6 lat
  • Ostatnio:ponad 4 lata
  • Postów:15
0

racja, troche zamotalem sprawe.
podrzucam kod jeszcze raz :
To wersja nie dzialajaca, ta, ktora wrzucilem na poczatku postu, dzialala w konstoli, gdy chce stworzyc metode i wyrzucic instrukcje warunkowe z controllera, wtedy wywala mi nulla.
DictionaryController, chcialbym by wygladal plus minus tak, bez instrukcji warunkowej

Kopiuj

@Scope(value = "session") 
@Controller
public class DictionaryController {

    private Random random = new Random();
    private User user = new User();

    private static String previousWord;

    @Autowired
    private LibraryRepository libraryRepository;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;


    @GetMapping("/game")
    public String showEnglish(@RequestParam(required = false) String name, ModelMap modelMap) {

        DictionaryService dictionaryService = new DictionaryService(name);

        modelMap.put("englishW", dictionaryService.getEWord());
        modelMap.put("polishW", dictionaryService.getPWord());
        modelMap.put("answer", dictionaryService.getMessage());


        return "game";
    }
}

tutaj jest klasa Service, w ktorej probuje stwrozyc metode losowania randomowej pary i ta metode wrzucic pozniej w DictionaryController

Kopiuj

public class DictionaryService {

        private String name;
        private Random random = new Random();
        private static String previousWord;

        private LibraryRepository libraryRepository;

        long count = libraryRepository.count();
        int index = random.nextInt((int) count);

       private String EWord = libraryRepository.findById(index).get().getEnglishWord();
       private String PWord = libraryRepository.findById(index).get().getPolishWord();

    public void setEWord(String EWord) {
        this.EWord = EWord;
    }

    public void setPWord(String PWord) {
        this.PWord = PWord;
    }

    public String getEWord() {
            return EWord;
        }

        public String getPWord() {
            return PWord;
        }

        public DictionaryService(String name){
            this.name = name;

        }
        public String getName() {
            return this.name;

        }

        public  String getMessage() {

//        if (name != null) {

            if (PWord.equals(name)) {
                return "dobrze";
            } else {
                return "zle";
            }
        }


    }



tak wyglada moj kod po stronie html

Kopiuj
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>Gra Słowna</title>
</head>
<body>
<h2>Podaj tłumaczenie słowa: </h2>
<form action="/game">  <!-- po wykonaniu akcji, wraca do result-->
    <p th:text="${englishW}"></p>

    <label>Przetłumacz</label>
    <!--<form action="/result">   -->
    <input type="text" name="name">
    <p th:text="${answer}"></p>

    <input type="submit" value="Sprawdz">

</form>
</body>
</html>

oraz libraryrepo, w ktorej jest adnotacja do pobierania wyrazow z bazy

Kopiuj
        import org.springframework.data.jpa.repository.Query;
        import org.springframework.data.repository.CrudRepository;

        import java.util.List;

public interface LibraryRepository extends CrudRepository<Library, Integer> {

    @Query("SELECT l FROM Library l where l.polishWord=?1")
    List<Library> findByPolishWord(String polishWord);

    @Query("SELECT l FROM Library l where l.englishWord=?1")
    List<Library> findByEnglishWord(String englishWord);
}

BA
There was an unexpected error (type=Internal Server Error, status=500). No message available java.lang.NullPointerException at dictionary_game.controller.DictionaryService.<init>(DictionaryService.java:16) at dictionary_game.controller.DictionaryController.showEnglish(DictionaryController.java:43) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
E9
Co kryje się pod 43 linijką DictionaryControllera?
BA
DictionaryService dictionaryService = new DictionaryService(name);
E9
  • Rejestracja:ponad 8 lat
  • Ostatnio:5 dni
  • Postów:216
0
Kopiuj
private LibraryRepository libraryRepository;
private String EWord = libraryRepository.findById(index).get().getEnglishWord();

Obstawiam że tutaj jest problem. Repository nie jest wstrzyknięte do tego serwisu, a Ty i tak próbujesz już go użyć.
Poza tym, oczekujesz że name przyjdzie jako parametr w zapytaniu /game, ale w HTMLu nie przekazujesz już tego parametru.

edytowany 2x, ostatnio: Emdzej93
BA
  • Rejestracja:około 6 lat
  • Ostatnio:ponad 4 lata
  • Postów:15
0

Jak to ugryzc w takim razie? Jesli robie to konsolowo, troche zmieniajac kod tak by byl jak na poczatku postu. zapytanie idzie do htmla i zwraca, sprwdzajac po instrukcji warunkowej czy wszystko jest ok. sytuacja dziala bez klasy service, ktora wtedy nie jest potrzebna

E9
  • Rejestracja:ponad 8 lat
  • Ostatnio:5 dni
  • Postów:216
0

Powinno wystarczyć, że do konstruktora DictionaryService dodasz parametr LibraryRepository

Kopiuj
public DictionaryService(String name, LibraryRepository libraryRepository){
           this.name = name;
           this.libraryRepository = libraryRepository;
       }

i przekażesz instancję którą masz w DictionaryController tworząc ten serwis

Kopiuj
 DictionaryService dictionaryService = new DictionaryService(name, libraryDictionary);

Ale generalnie przemyślałbym design tego wszystkiego, bo to trochę łatanie dziur w tonącym statku ;)

edytowany 1x, ostatnio: Emdzej93
BA
  • Rejestracja:około 6 lat
  • Ostatnio:ponad 4 lata
  • Postów:15
0

Tez rozwazalem tak jak ty piszesz, niestety dalej jest kaplica

E9
  • Rejestracja:ponad 8 lat
  • Ostatnio:5 dni
  • Postów:216
1

Jak wspomniałem, używasz libraryRepository zanim go zanicjalizujesz.
IIRC, kolejność tworzenia obiektu przebiega tak:

  1. Zmienne statyczne
  2. super() w kosntruktorze
  3. zmienne klasowe
  4. reszta konstruktora

U Ciebie wygląda to tak

Kopiuj
    private Random random = new Random();
    private static String previousWord;
    private LibraryRepository libraryRepository;
    
    long count = libraryRepository.count();
    
    public DictionaryService(String name, LibraryRepository libraryRepository) {
        this.name = name;
        this.libraryRepository = libraryRepository;
    }
  1. Zmienna statyczna previousWord - zostałaby zaincjalizowana jako pierwsza, jakbyś coś do niej przypisał, ale że tego nie zrobiłeś to jest nadal nullem.
  2. super() pomijamy bo go tutaj nie ma jawnie wpisanego
  3. Teraz następuje inicjalizacja zmiennych nie statycznych klasy, tworzony jest new Random(), ale nie przypisujesz nic do libraryRepository więć nie jest on tworzony, zostaje on == null;
    W następnej linicje jednak, próbujesz stworzyć zmienną count() która jest metodą nie utworzonego obiektu libraryRepository - tutaj leci pierwszy null pointer.
  4. Dopiero w tym momencie możesz korzystać z libraryRepository, bo dopiero teraz ta zmienna jest stworzona w konstruktorze.

Jeżeli potrzebujesz stworzyć zmienną na podstawie metody z libraryRepository musisz to zrobić PO zainicjalizowaniu libraryRepository wewnątrz swojej klasy.

edytowany 2x, ostatnio: Emdzej93
BA
  • Rejestracja:około 6 lat
  • Ostatnio:ponad 4 lata
  • Postów:15
0

dzieki ci za wszystkie skazowki :) problem rozwiazany. Tak jak pisales, duzo u mnie problemow z implementacja repository. dodatkowo jak sytuacje opanowalem, w bazie danych wartosci zaczynaly sie od 1, a w randomie liczylo od 0, wiec tu tez byl nullpointer, wiec rozwiazaniem bylo albo dodac+1 do indexu, albo zmienic recznie w bazie danych. Co do implementacji, poradzilem sobie za pomoca @Autowired. Postaram sie zrobic porzadek w kodzie miedzy innymi wedlug twoich instrukcji

Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)