When I start my App the first time I click on the map and click on the submit button, I am getting an Error "type=Unsupported Media Type, status=415", when I click back and do the same thing again, it is working perfectly fine and doing what I am expecting. I am also getting a WARN : "org.springframework.web.HttpMediaTypeNotSupportedException: Content-Type 'application/x-www-form-urlencoded;charset=UTF-8' is not supported". I have no ider why this is happening, since it should return application/json. When I use POST with Postman it is also returning the correct json.It should also redirect to "/result" when I click the button, but it is stayin on "/game". Again on second try, it is working fine.
this is my JS:
const {Map} = await google.maps.importLibrary("maps");const {LatLng} = google.maps.importLibrary("core");const yearSlider = document.getElementById("yearSlider");const yearValue = document.getElementById("yearValue");const map = new Map(document.getElementById("googleMap"), { zoom: 0, center: {lat: 0, lng: 0}, mapTypeControl: false, fullscreenControl: false, streetViewControl: false, zoomControl: false, keyboardShortcuts: false, minZoom: 1, restriction: { latLngBounds: { north: 85, south: -85, west: -180, east: 180, } },});let guessMarker = null;let guessLat;let guessLng;let guessYear;map.addListener("click", (mapsMouseEvent) => { if (guessMarker) { guessMarker.setPosition(mapsMouseEvent.latLng); } else { guessMarker = new google.maps.Marker({ position: mapsMouseEvent.latLng, map: map, title: "My Guess!" }); } guessLat = mapsMouseEvent.latLng.lat(); guessLng = mapsMouseEvent.latLng.lng();});yearValue.textContent = yearSlider.value;yearSlider.addEventListener("input", function () { yearValue.textContent = this.value;});const fetchButton = document.getElementById("fetchButton");fetchButton.addEventListener("click", () => { fetchCoordinates();});function fetchCoordinates() { guessYear = yearSlider.value; fetch("/game", { method: 'post', headers: {'Content-Type': 'application/json' }, body: JSON.stringify({guessLat, guessLng, guessYear}) }).then(response => { if (response.ok) { console.log("ok!!!") window.location.href = "/result"; } else { console.log("not redirecting") } })}const expandable = document.getElementById("expandable");expandable.addEventListener("mouseenter", enlargeFunc);function enlargeFunc() { expandable.style.width = "700px"; expandable.style.height = "700px";}expandable.addEventListener("mouseleave", decrementFunc);function decrementFunc() { expandable.style.width = "150px"; expandable.style.height = "150px";}const container = document.getElementById("container");const imageZoom = document.getElementById("image-zoom");let scale = 1;container.addEventListener("wheel", zoomFunc);function zoomFunc(event) { console.log("zoooooom!"); event.preventDefault(); const delta = Math.max(-1, Math.min(1, event.deltaY)) if (delta > 0) { scale -= 0.1; } else { scale += 0.1; } imageZoom.style.transform = `scale(${scale})`;}
The HTML :
<!doctype html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Game</title><link rel="stylesheet" href="/css/styles.css"></head><body><div id="container"><div id="image-zoom"><img src="" alt="image"></div></div><footer><div class="expandable" id="expandable"><div class="expandable__content"><div class="mapSearch" id="googleMap"></div><div class="form"><form action="/game" method="post"><label for="yearSlider">Year input</label><input name="guessYear" type="range" min="1900" max="2024" value="2024" class="slider" id="yearSlider"><p>Year: <span id="yearValue">2024</span></p><button class="button" id="fetchButton">Submit</button></form></div></div></div></footer></body><script> (g => { var h, a, k, p = "The Google Maps JavaScript API", c = "google", l = "importLibrary", q = "__ib__", m = document, b = window; b = b[c] || (b[c] = {}); var d = b.maps || (b.maps = {}), r = new Set(['maps']), e = new URLSearchParams, u = () => h || (h = new Promise(async (f, n) => { await (a = m.createElement("script")); e.set("libraries", [...r] +""); for (k in g) e.set(k.replace(/[A-Z]/g, t => "_" + t[0].toLowerCase()), g[k]); e.set("callback", c +".maps." + q); a.src = `https://maps.${c}apis.com/maps/api/js?` + e; d[q] = f; a.onerror = () => h = n(Error(p +" could not load.")); a.nonce = m.querySelector("script[nonce]")?.nonce || ""; m.head.append(a) })); d[l] ? console.warn(p +" only loads once. Ignoring:", g) : d[l] = (f, ...n) => r.add(f) && u().then(() => d[l](f, ...n)) })({ key: "MAPS_KEY", v: "weekly", });</script><script type="module" src="/js/googleMap.js"></script></html>
and the Controller:
package org.softuni.finalproject.web;import org.softuni.finalproject.model.UserGuess;import org.softuni.finalproject.service.GameSession;import org.springframework.core.io.ClassPathResource;import org.springframework.http.MediaType;import org.springframework.http.ResponseEntity;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RestController;import java.io.IOException;import java.nio.charset.StandardCharsets;import java.util.Objects;@RestControllerpublic class GameController { private final GameSession gameSession; public GameController(GameSession gameSession) { this.gameSession = gameSession; } @GetMapping("/game") public ResponseEntity<String> showGameWindow() throws IOException { ClassPathResource resource = new ClassPathResource("templates/game.html"); String htmlContent = new String(Objects.requireNonNull(resource.getInputStream().readAllBytes()), StandardCharsets.UTF_8); String imageUrl = this.gameSession.getLocation(); htmlContent = htmlContent.replace("<img src=\"\" alt=\"image\">", "<img src=\"" + imageUrl +"\" alt=\"image\"/>"); return ResponseEntity.ok() .contentType(MediaType.TEXT_HTML) .body(htmlContent); } @PostMapping("/game") public ResponseEntity<UserGuess> getUserGuess(@RequestBody UserGuess userGuess) { this.gameSession.setUserGuess(userGuess); System.out.println(userGuess.toString()); return ResponseEntity.ok().body(userGuess); }}
It was working fine, before adding the zoom function. I tryed to remove it, but nothing changes. So I guess I did something wrong even before that, but I am not able to find what the problem is.
EDIT: when I try to use different HTML like this for example:
<!doctype html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><link rel="stylesheet" href="/css/styles.css"><script> (g => { var h, a, k, p = "The Google Maps JavaScript API", c = "google", l = "importLibrary", q = "__ib__", m = document, b = window; b = b[c] || (b[c] = {}); var d = b.maps || (b.maps = {}), r = new Set(['maps']), e = new URLSearchParams, u = () => h || (h = new Promise(async (f, n) => { await (a = m.createElement("script")); e.set("libraries", [...r] +""); for (k in g) e.set(k.replace(/[A-Z]/g, t => "_" + t[0].toLowerCase()), g[k]); e.set("callback", c +".maps." + q); a.src = `https://maps.${c}apis.com/maps/api/js?` + e; d[q] = f; a.onerror = () => h = n(Error(p +" could not load.")); a.nonce = m.querySelector("script[nonce]")?.nonce || ""; m.head.append(a) })); d[l] ? console.warn(p +" only loads once. Ignoring:", g) : d[l] = (f, ...n) => r.add(f) && u().then(() => d[l](f, ...n)) })({ key: "MAPS_KEY", v: "weekly", });</script></head><body><div class="mainContainer" id="mainContainer"><div class="header"><h1>Make your guess!</h1><p>Image description</p></div><div class="gameContainer"><div class="imageContainer" id="pictureContainer"><img src="" alt="image"></div></div></div></body><footer><div class="expand"><div class="mapSearch" id="googleMap"></div><script type="module" src="/js/googleMap.js"></script><form action="/game" method="post"><input name="guessYear" type="range" min="1900" max="2024" value="2024" class="slider" id="yearSlider"><p>Year: <span id="yearValue">2024</span></p></form><button class="button" id="fetchButton">Submit</button></div></footer></html>
it is working ok, but I still can't find why is the first one not working and what is different...