3 import java.io.IOException;
4 import java.io.PrintWriter;
5 import java.util.HashMap;
7 import java.util.concurrent.CompletableFuture;
9 import javax.servlet.http.HttpServletRequest;
10 import javax.servlet.http.HttpServletResponse;
12 import jalview.bin.Cache;
13 import jalview.rest.RestHandler.Status;
15 public abstract class AbstractEndpointAsync extends AbstractEndpoint
17 public AbstractEndpointAsync(API api, String path, String name,
18 String parameters, String description)
20 super(api, path, name, parameters, description);
23 protected String idExtension = null;
25 protected String id = null;
27 protected CompletableFuture<Void> cf = null;
29 protected Map<String, CompletableFuture<Void>> cfMap = new HashMap<>();
31 protected Map<String, String> stringsPassedToProcessAsync = new HashMap<>();
33 protected void setCompletableFuture(CompletableFuture<Void> cf)
37 cfMap.put(getId(), cf);
40 protected CompletableFuture<Void> getCompletableFuture()
42 if (cf == null && getId() != null && cfMap.get(getId()) != null)
43 cf = cfMap.get(getId());
47 protected void setId(String id)
52 protected void setIdExtension(String idExtension)
54 setId(getPath() + "::" + idExtension);
57 protected String getId()
63 * Override the three methods
64 * initialise (get parameters, set id (extension), set cf if using an existing one)
65 * process (what to do in the cf if not using an existing one)
66 * finalise (extra stuff to do at the end of the first call to this)
68 protected void initialise(HttpServletRequest request,
69 HttpServletResponse response)
71 // should be overridden
72 // must setId(request, extension)
76 protected abstract void processAsync(HttpServletRequest request,
77 HttpServletResponse response, final Map<String, String> finalMap);
79 protected void finalise(HttpServletRequest request,
80 HttpServletResponse response)
86 public void processEndpoint(HttpServletRequest request,
87 HttpServletResponse response)
90 initialise(request, response);
92 if (checkStatus(request, response, Status.STARTED))
94 String finishedString = null;
95 if (getStatus() == Status.FINISHED)
97 finishedString = finished(request, response);
99 returnStatus(request, response, finishedString);
103 if (getCompletableFuture() == null)
105 final Map<String, String> finalStringMap = stringsPassedToProcessAsync;
106 setCompletableFuture(CompletableFuture.runAsync(() -> {
108 this.processAsync(request, response, finalStringMap);
111 addWhenCompleteCompletableFuture();
114 finalise(request, response);
116 returnStatus(response);
117 changeStatus(Status.IN_PROGRESS);
120 protected void atEnd()
124 protected String finished(HttpServletRequest request,
125 HttpServletResponse response)
131 * Shared methods below here
134 protected String setId(HttpServletRequest request, String extension)
136 String idString = request.getParameter("id");
137 if (idString == null)
139 setIdExtension(extension);
148 protected void changeStatus(Status status)
151 // don't change a job's status if it has finished or died
152 if (getStatus() == Status.FINISHED || getStatus() == Status.ERROR)
154 API.getStatusMap().put(id, status);
157 protected Status getStatus()
160 return API.getStatusMap().get(getId());
163 protected void returnStatus(HttpServletResponse response)
165 returnStatus(null, response, null);
168 protected void returnStatus(HttpServletRequest request,
169 HttpServletResponse response, String message)
174 PrintWriter writer = response.getWriter();
177 writer.write("id=" + id + "\n");
180 if (API.getRequestMap().get(id) != null)
184 "request=" + API.getRequestMap().get(id).toString() + "\n");
186 if (getStatus() != null)
188 if (getStatus() == Status.ERROR)
190 response.setStatus(500);
192 writer.write("status=" + getStatus().toString() + "\n");
196 writer.write(message);
198 } catch (IOException e)
204 protected boolean checkStatus(HttpServletRequest request,
205 HttpServletResponse response)
207 return checkStatus(request, response, null);
210 protected boolean checkStatus(HttpServletRequest request,
211 HttpServletResponse response, Status set)
214 Status status = getStatus();
219 API.getRequestMap().put(id, request.getRequestURI());
228 protected void addWhenCompleteCompletableFuture()
231 cf.whenComplete((Void, e) -> {
234 Cache.error("Endpoint job " + id + " did not complete");
236 changeStatus(Status.ERROR);
240 Cache.info("Endpoint job " + id + " completed successfully");
241 changeStatus(Status.FINISHED);