diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedRaceListResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedRaceListResource.java
index ef40af1f946..a23568bfd8f 100644
--- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedRaceListResource.java
+++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedRaceListResource.java
@@ -13,7 +13,9 @@ import java.util.function.Predicate;
import java.util.stream.Collectors;
import javax.ws.rs.DefaultValue;
+import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
+import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
@@ -59,6 +61,21 @@ public class TrackedRaceListResource extends AbstractSailingServerResource {
return getJsonResponse(streamingOutput(detailedRaceListJsonSerializer.serialize(detailedRaceInfo)));
}
+ /**
+ *
POST variant of the {@link #raceList(Boolean, String, String)} interface. Just uses HTTP post to circumvent HTTP 418
+ * issues with large number of events.
+ * Parameters must be provided within a form body.
+ * @see {@link #raceList(Boolean, String, String)}
+ */
+ @POST
+ @Produces(CONTENT_TYPE_JSON_UTF8)
+ @Path("getRaces")
+ public Response raceListPost(@FormParam("transitive") @DefaultValue("false") Boolean transitive,
+ @FormParam("events") @DefaultValue("") String strEvents,
+ @FormParam("pred") @DefaultValue("excl") String predicate) {
+ return raceList(transitive, strEvents, predicate);
+ }
+
/**
* Returns a list of tracked races. By default, only TrackedRaces from the local instance are returned. The entries
* are grouped by the remote URL from where they originated. Local entries have a {@code null} value for the
diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RemoteSailingServerSet.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RemoteSailingServerSet.java
index f4fbd4945b0..d490e23fa65 100644
--- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RemoteSailingServerSet.java
+++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RemoteSailingServerSet.java
@@ -3,7 +3,9 @@ package com.sap.sailing.server.impl;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
+import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
@@ -15,6 +17,7 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
@@ -48,6 +51,7 @@ import com.sap.sailing.server.gateway.deserialization.impl.TrackingConnectorInfo
import com.sap.sailing.server.gateway.deserialization.impl.VenueJsonDeserializer;
import com.sap.sailing.server.gateway.serialization.impl.DetailedRaceInfoJsonSerializer;
import com.sap.sailing.server.gateway.serialization.impl.SimpleRaceInfoJsonSerializer;
+import com.sap.sse.common.Duration;
import com.sap.sse.common.Util;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.concurrent.LockUtil;
@@ -188,11 +192,13 @@ public class RemoteSailingServerSet {
private void updateRemoteServerTrackedRacesCacheSynchronously(RemoteSailingServerReference ref) {
Util.Pair, Exception> result;
try {
- final URL raceListURL = getRaceListURL(ref);
- logger.fine("Updating racelist for remote server " + ref + " from URL " + raceListURL);
+
+ logger.fine("Updating racelist for remote server " + ref + " from URL " + ref.getURL());
+
final SimpleRaceInfoJsonSerializer deserializer = new SimpleRaceInfoJsonSerializer();
final Set races = new HashSet<>();
- for (Object remoteWithRaces : getJsonFromRemoteServerSynchronously(ref, raceListURL)) {
+
+ for (Object remoteWithRaces : getJSONFromRemoteRacesListSynchronously(ref)) {
JSONObject remoteWithRacesAsJson = (JSONObject) remoteWithRaces;
String remoteUrlAsString = (String) remoteWithRacesAsJson
.get(DetailedRaceInfoJsonSerializer.FIELD_REMOTEURL);
@@ -235,7 +241,7 @@ public class RemoteSailingServerSet {
}
/**
- * Build the URL for retrieving the remote servers race list. This is complemented by the endpoint here:
+ * Build the URL for retrieving the remote servers race list. This is complemented by the end point here:
* {@link com.sap.sailing.server.gateway.jaxrs.api.TrackedRaceListResource#raceList(Boolean, String, String)}
* @param ref the remote reference
* @return the URL for retrieving the remote races.
@@ -244,18 +250,6 @@ public class RemoteSailingServerSet {
private URL getRaceListURL(RemoteSailingServerReference ref) throws MalformedURLException {
URL remoteServerBaseURL = ref.getURL();
String endpoint = "/trackedRaces/getRaces?transitive=true";
- if (!ref.getSelectedEventIds().isEmpty()) {
- endpoint += "&events=";
-
- Iterator iter = ref.getSelectedEventIds().iterator();
- while (iter.hasNext()) {
- endpoint += iter.next().toString();
- if (iter.hasNext()) {
- endpoint += ",";
- }
- }
- endpoint += "&pred=" + (ref.isInclude() ? "incl" : "excl");
- }
return getEndpointUrl(remoteServerBaseURL, endpoint);
}
@@ -346,6 +340,45 @@ public class RemoteSailingServerSet {
updateCache(ref, result, cachedStatisticsByYearForRemoteSailingServers::put);
}
+ private JSONArray getJSONFromRemoteRacesListSynchronously(final RemoteSailingServerReference ref)
+ throws MalformedURLException, IOException, ParseException {
+ JSONArray data;
+ final URL url = getRaceListURL(ref);
+ final StringBuffer formParams = new StringBuffer("transitive=true");
+ if (!ref.getSelectedEventIds().isEmpty()) {
+ formParams.append("&events=");
+ Iterator iter = ref.getSelectedEventIds().iterator();
+ while (iter.hasNext()) {
+ formParams.append(URLEncoder.encode(iter.next().toString(), "utf-8"));
+ if (iter.hasNext()) {
+ formParams.append(URLEncoder.encode(",", "utf-8"));
+ }
+ }
+ formParams.append("&pred=" + (ref.isInclude() ? "incl" : "excl"));
+ }
+ HttpURLConnection urlConnection = (HttpURLConnection) HttpUrlConnectionHelper.redirectConnection(url,
+ Duration.ONE_SECOND.times(1000), "POST", (connection) -> connection
+ .setRequestProperty("Content-Type", "application/x-www-form-urlencoded"),
+ Optional.of(outputStream -> {
+ try (OutputStreamWriter writer = new OutputStreamWriter(outputStream, "utf-8")) {
+ writer.write(formParams.toString());
+ }
+ }));
+ final int responseCode = urlConnection.getResponseCode();
+ if (responseCode == 200) {
+ try (BufferedReader bufferedReader = new BufferedReader(
+ new InputStreamReader(urlConnection.getInputStream(), "utf-8"))) {
+ JSONParser parser = new JSONParser();
+ data = (JSONArray) parser.parse(bufferedReader);
+ }
+ } else {
+ // fallback to old interface when new interface was not found.
+ // can be removed when all servers are upgraded
+ data = getJsonFromRemoteServerSynchronously(ref, url);
+ }
+ return data;
+ }
+
private JSONArray getJsonFromRemoteServerSynchronously(RemoteSailingServerReference ref,
final URL url) throws IOException, ParseException {
logger.fine("Updating data for remote server " + ref + " from URL " + url);