0

I am starting to develop a REST API with Jersey to retrieve a schedule for a given sport tournament. The client sends a JSON containing a tournament with its different categories, domain, definitions and configuration. This will be unmarshalled by Jackson. And the response includes a JSON with the calculated schedule for that tournament, marshalled by Jackson as well.

I want to make the API as "API-like" as possible, in the sense of common APIs like weather APIs or maps APIs, where the client-server interaction is a direct, concise request-response-type operation, in this case that'd be "send a tournament, get a schedule", where no association between the client and the instantiated references (or conceptual associations) are left in the server at all. I guess the word for this would be "stateless".

However, I need some sort of reference to the tournament that has been sent in order to perform subsequent operations on that instanciated object. The case would be, for example, to retrieve the "next" schedule for the tournament. There are potentially many other cases.

Since I am using Constraint Programming to calculate the schedules, I can get all the possible combinations of schedules for a given tournament. But a direct operation as described just gets rid of the instance as soon as the schedule is returned in the response, therefore I wouldn't be able to invoke methods such as tournament.nextSchedules() because the tournament object simply wouldn't be there. So I was suggested to use sessions. Then, I assume I would have a map of session ID and a Tournament instance in my web service Jersey class:

@Path("eventscheduler")
public class EventSchedulerService {
    private Map<String, Tournament> tournaments = new HashMap<>();
}

Then, if I wanted to perform an action on a particular tournament I would just have to retrieve its corresponding mapping to a session ID, which can be passed in the URL as a @PathParam.

Here are my questions:

  • How could I do this with Jersey? How can I generate a session and store it as intended? Note that this has nothing to do with security. The sole purpose of using sessions is to be able to identify a particular reference of a Tournament.
  • How can I set an expiration time on a session? I wouldn't want to have a client forever bound to a particular tournament instance. Although I will probably make a method to explicitly unbound a client to a session, as well as getting rid of the mapping, I'd also want to have it expire and removed from the dictionary as well. How can this be done?

Note as well that no databases are being used and are not intended to be used since it's not the objective of this project and they shouldn't be needed.

  • I would urge you not to do this. Sessions have their purposes, but in an API such as you're describing, make the tournament IDs visible to the client. Require that the tournament ID be present in requests. – slim May 31 '16 at 10:27
  • But there is no such thing as a tournament ID. And there's no concept of "user". I only need means to identify the tournament the client is referring to "right now" (that particular instance) to perform subsequent operations if wished. I was suggested using sessions (to be able to make that identification, I assume). – dabadaba May 31 '16 at 10:49
  • 1
    A resource is a unit of a REST API. Each resource has a corresponding URI which is used by clients to interact with the associated resource. A resource has a representation (call simply "resource representation") that a client can retrieve or modify. The main problem I see is that you are focusing on level-low details about your implementations and stuff like that, rather than thinking with an high level of abstraction... through resources. You are basically thinking first on "how can i do that" rather thinking "what i need to do" (and thus, what i need to represent) – AilurusFulgens May 31 '16 at 13:31
  • 1
    Don't use session. Use URLs. When the client creates a new Tournament resource and PUTs it or POSTs it to the server the server should map the internal tournament object to a URL, and return that to the client. If the client wants to access that Tournament again it goes to that URL. – Cormac Mulhall May 31 '16 at 13:34
  • 1
    @dabadaba A comment might be not sufficient, take a look at chapter 8 of this book: goo.gl/FkTAuR (2 first pages at least). The author present how to design resources. Applied to your case, it means: what is the data model of a schedule and a tournament ? Does they need to have an associated resource ? If yes, think about what is accepted and also served to the clients ? Does a relationship exists between tournament and schedule ? If yes, use links (chapter 8, p. 218). I totally agree w the answer, that focus on resource not on implementation (sorry if i'm rude in my comments! ;-) !) – AilurusFulgens May 31 '16 at 14:54
4

It should be unnecessary to use sessions for this scenario.

When the client creates a new Tournament resource (represented in JSON) it can PUT or POST that resource to the server. Which one you choose will depend on who is responsible for the unique identifier for the Tournament. If the client already knows what the URL should be for that Tournament (say it is based of the name) it can just PUT that resource to that URL on the server (eg. /tournaments/west_coast_regionals_2016)

If the server determines the URL then the client should POST the Tournament resource to some collection resource (eg. /tournaments) and that resource generates a unique id for the resource and returns it to the client.

Either way the client gets back the URL of the resource it just sent to the server. If it ever wants to access that resource again it just uses that URL.

GET /tournaments/west_cost_regionals_2016

And the server returns that resource to the client. If the server has worked out some schedule then it can further information to the body of the response, or the way some do it is to add a new resource that contains just the next event information

GET /tournaments/west_cost_regionals_2016/next_event

Using a session should be completely unnecessary.

  • I absolutely understand my issue thanks to this answer, this helped me much more than that down vote without arguments. Did you have in mind that I am not planning on using DBs? I am used to that kind of URLs when those resources are stored in databases. But does it still make sense to just have them persisted in memory? I guess it does right? It's a resource no matter where it is stored. – dabadaba May 31 '16 at 14:27
  • A side quesion, related to my last question in my original post. I really wouldn't want to keep those instances in memory so resources (server resources) are not abused too much. What would be the best way to set an expiration time on a newly added resource? – dabadaba May 31 '16 at 14:29
  • 1
    Using a DB or not using a DB is largely irrelevant to REST. That is a server side implementation detail. The point is that every resource must have a URL and the URL is how the client and server know they are referencing the same resource. – Cormac Mulhall May 31 '16 at 14:38
  • An expiration time on the resource is up to you (again server side implementation detail). Set a time that makes sense for usage patterns. As far as REST is concerned all you have to do is tell the client that the resources is gone when it might request it after you delete it. You can use the 410 Gone response, or if you don't want to even keep a record that you deleted the object, a 404 Not Found. The former is better for the client, but would require you to keep a record of objects you have deleted. – Cormac Mulhall May 31 '16 at 14:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.