Problem z kontrolerem

0

Dobry wieczór!

Buduje aplikację REST na serwerze Tomcat, mam jednak pewien problem z kontrolerem który odpowiada za obsługę wywołania strony i przekazanie informacji JSON.

@Controller 
public class HomeController {
    
    @Autowired
    DatabaseRepository databaseRepository;
    
    @RequestMapping( path = "/", produces = "text/html")
    public String homeController(){
        return "/templates/home.html";
    }
    
    @RequestMapping( path = "/", method = RequestMethod.GET, produces = "application/json", headers = "Accept=application/json")
    public @ResponseBody List<Game> returnRandomGames(){
        return databaseRepository.getRandomGames(9);
    }
    
}

W założeniu kontroler ma obsługiwać stronę domową (przekazywać plik html) a także obsłużyć żądanie napisane w Angularze:

var app = angular.module('displayGames', ['ngRoute']);

app.service('getRandomGamesService', function() {
    var randomGames;
    
    this.getRandomGames = function($http){ 
        return $http( {
            headers: {
                "X-Testing" : "testing"
            },
            method: 'GET',
            url: '',
            accept: "application/json"
          }).then(function successCallback(response) {
              randomGames = response.data;
              return randomGames;
            }, function errorCallback(response) {
              window.alert("Fail!");
            });
    };
    
});

app.controller('randomGames', function($scope, $http, getRandomGamesService ){
    
    $scope.submit = function(){
        getRandomGamesService.getRandomGames($http).then( function(randomGames) {    
            window.alert(randomGames);
            $scope.games = randomGames;
        });    
    };
    
});

Żądanie te pobiera listę produktów w JSON po czym je wypisuje na stronie domowej.

**Problem polega na tym, że żądanie nie zawsze działa. Gdy odświeżę stronę (zazwyczaj) żądanie pobiera stronę html zamiast pliku JSON przez co wychodzą bzdury. ** Co ciekawe, gdy włączę Chrome Dev Tools to żądanie *zawsze *działa poprawnie i nie jestem w stanie zobaczyć co jest nie tak. Zgaduje że problem leży po stronie kontrolera więc piszę to w dziale javy.

  1. Ktoś ma może jakiś pomysł co jest źle?
  2. Czy taka "architektura" kontrolera, jest dobra, tzn. by dla jednej ścieżki generował różne zasoby (tutaj html lub JSON)?

EDIT: Dobra, jednak Chrome DT nie mają nic do rzeczy bo dla nich też czasami nie działa. W sumie nie jestem w stanie powiedzieć od czego zależy że te requesty działają lub nie. **Obecnie działa to w taki sposób, że pierwszy request po odświeżeniu strony nigdy nie działa, a kolejne zazwyczaj już tak. ** Wydaje mi się że błąd jest głupi ale nie potrafię go znaleźć.
EDIT2: Wstawiłbym info o requeście ale znowu wszystko działa gdy mam włączony CDT :/. Tylko po wyłączeniu go dzieje się sytuacja opisana powyżej - pierwszy request nie działa, kolejne już tak.

1

Nie, nie jest to dobra architektura w żaden sposób. Rozumiem że mogłoby zwracać XML albo JSON dla jednego endpointa ale nie HTML lub JSON.
I nie jest dobre wywoływanie Repository bezpośrednio w kodzie kontrollera i zwracanie czystej ecni :)

1
  1. Ja w ogóle nie rozumiem co ty tam robisz. Masz 2 mappingi na TEN SAM URL o_O i dziwisz sie że coś dziwnego sie dzieje? Skąd niby Spring miałby wiedzieć co ma zwracać jak wywołujesz /? Takie poleganie na headerach jest dziwnym pomysłem. Zrób po ludzku osobne endpointy. Bo rozumiesz chyba że metody kontrolera mogą (powinny!) mieć różne path?
  2. Używaj @RestController, omijając dodatkowe dekoratory
0

Na początek przygody z RESTami proponuję lekturę.

0

@tomcki.pl:
Dzięki, postaram się poczytać.

@scibi92
Rozumiem, jak w takim razie komunikować się z repository?

@Shalom
No właśnie nie byłem pewien czy 'powinny', bo o że mogą to wiedziałem :/.

Problem rozwiązany, rzeczywiście bez sensu było kombinowanie z headerami.

1

Nie wydaje mi się, żeby poleganie na headerach było naganne. Tak się wersjonuje restowe api i w ogóle jest to zgodne z filozofią rest. Po to też jest parametr produces. headers nie powinno tu być w ogóle potrzebne. Gdybyś więc chciał dalej iść tą ścieżką, to zrób tak:

  1. Puść wszystko przez Fiddlera i sprawdź, jaki nagłówek wysyła przeglądarka.
  2. Ujednolić te mappingi - albo get albo wszystko, tak samo w obu przypadkach. Niech różnią się tylko produces. Może to nieistotne, ale przynajmniej na początek, do uruchomienia.
  3. Wypisz nagłówki każdego requesta w obsłudze, to powinno doprowadzić do jakichś wniosków.
  4. Zastanów się, co się ma stać, jeżeli ktoś wyśle żądanie z acceptem na oba typy albo na żaden.
  5. Może trzeba użyć produces=!text/html czy coś w tym stylu

Just like with consumes, producible media type expressions can be negated as in !text/plain to match to all requests other than those with an Accept header value of text/plain.

Koncepcyjnie przychylałbym się najbardziej do takiego rozwiązania: jeden mapping na produces=text/html, a drugi na produces=!text/html. Resztą zająłby się ewentualny content-negotiation w springu.

0

Gdy odświeżę stronę (zazwyczaj) żądanie pobiera stronę html zamiast pliku JSON przez co wychodzą bzdury.

Czyli tak, jakby przeglądarka cache'owała zawartość. Bug w przeglądarce... a może nasz? Jeżeli zwracamy różną zawartość dla tego samego urla, to zmienna zawartość od czegoś zależy. "Różni się", czyli "vary", a więc trzeba zwracać Vary: Accept.

Ciekawe, czy by pomogło...

0

@jarekczek:

Dzięki za pomysł, szczerze powiedziawszy zrobiłem jak poradził Shalom i nie chciało mi się już nad tym siedzieć :). Może innym razem.

Tak czy inaczej wciąż mnie zastanawia czemu tylko pierwsze zapytanie po odświeżeniu źle działało, a kolejne już dobrze. Cachowanie chyba odpada, bo w Chrome DT wyłączyłem opcje cachowania.

0

Może to było źle:

$http( {
  [...]
  accept: "application/json"

W dokumentacji nie widzę czegoś takiego. Ja testuję bezpośrednio przez XMLHttpRequest i nie umiem powtórzyć Twojego błędu. Po prostu stwierdziłem, że warto się tym zainteresować, dla własnej korzyści :)

W Javie takiego błędu nie da się popełnić, wychodzi tutaj nieprzyjazność Javascriptu.

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