-
Notifications
You must be signed in to change notification settings - Fork 558
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Primary identifier missing #13
Comments
Jon, |
In a REST context the URI is the identifier (hence the name Unique Resource Identifier). If there's a business key inside the entity on the domain class (like a customer id or the like) I wouldn't wanna use this as primary key actually. So we decided to keep the technical id out of the representation. The primary reason is the following: if the representation contains the backend id of the entity - let's assume "1" - and you'd issue a PUT request to /entities/3, which entity would get updated? Would the entity with id 1 (as identified by the URI) get updated to get an id of 3? Should we silently ignore the id field? I think you get the point. Resource identification is done through URIs only. |
Hi Oliver, Besides that it is clear that the URI, is always the primary identifier but only for the REST stuff. In case of some application internal logic I would not want to use the whole URI at all. And additionally: as long as the user follows the HATEOAS principles and only uses the links for CRUD operations I don't see any disadvantage? Sorry Oliver, I am still not confident with this. |
A REST client does not know about a PK. It also doesn't know about it being encoded in the URI. Essentially that we use the PK in the URI is a URI design decision to make them readable easily. This comes with the side effect that to someone seeing the URI easily being able to get it's structure and generally being able to defer URIs to other resources. The crucial point is: a REST client is not aware of that. All it knows is that there's a rel of Yet another question to emphasize what I am shooting for: we also don't just add the PK of a related resource into the representation additionally so why would you with the PK of the resource you get the current representation for. |
Perhaps we are talking past each other: But in my opinion the argumentation contradicts itself. First you say the REST client does not know about a PK and you just use them to make them easily readable, which means, you could have chosen/choose in future a different one. Following this argumentation, the REST client is not allowed to rely on a specific property for REST stuff as the primary key to build URIs manually. Using the primary key would in this case violate the architecture. If you conclude this approach, id is just a normal property as all others are. Removing it makes it to a property with a special purpose and the PK. For me these are two different layers:
Each of them should be independent of each other and should not add restrictions for cases, in which the user might possibly use it against all architectural principles. |
I think you're mixing up cause and effect here. A PK is some property artificially introduced to the server side model of a domain concept. Taking it a step back it's even as follows: you have domain concepts. Some of these concepts have a lifecycle which by definition makes them an entity. As you need to identify those to keep track of the lifecycle, you introduce an identifier. Now here's the trick: to make sure you can separate between actual domain properties and the ones introduced technical reason I'd recommend not to mixup business identifiers with technical ones. So I think the following design approach is pretty consistent:
Thus why would you expose the server side store identifier? This is actually leaking implementation details. You could argue it is as the PK is part of the URI already. But that's an orthogonal URI design decision which ultimately doesn't even have to be the case. You could expose customers via REST is not about CRUD on entities or exposing entities 1:1 to the web. |
I am aware of that. It was just used as placeholder for "resource identifier". And I do understand your argumentation, but unless I think it is not a matter of architecture than just more a matter of taste.
There are two reasons:
Regarding my last post as well I need to correct myself:
As we have both arguments for and against it, I think the best way to handle this would be making the REST identifiers optionally included in the response body. By default it is turned off and if user likes to enable it, he needs to adjust some setting in the configuration. |
That's my point: you would not do that in any case as this assumes the client knows that the URI contains a different kind of identifier which it must not. So you'd either compare URIs or some arbitrary off-band identifier like a customer number.
That might be the case but I clearly vote a -1 on this one as it just breaks well-established principles in information hiding and pretty much breaks the abstraction purpose of a REST interface. So I think we end up on agreeing to disagree on this one, which is perfectly fine :). Good reference discussion in any case! |
Ok I would vote + 1 and the rest could decide! :-)
Indeed to both :-). |
Since this would be really useful to integrate spring data rest with most client-side libs, those well-established principles seem a bit ivory-towerish to me ;-). A huge +1 from my part. In fact, I've made it work by simply adding to org.springframework.data.rest.webmvc.EntityToResourceConverter a quick hack at the end of the convert method: @Override public Resource convert(Object source) { ... //hack to serialize the ID of the entity AttributeMetadata idAttribute=entityMetadata.idAttribute(); if(idAttribute!=null){ Object val= entityMetadata.idAttribute().get(source); Object name=idAttribute.name(); if(val!=null && name!=null){ entityDto.put(entityMetadata.idAttribute().name(),val); } } // END Hack return new EntityResource(entityDto, links); |
I'd argue this is implementing HTTP as it is specified. Of course, people also have built web applications piping non-idempotent operations through get request for ages and called that "pragmatic". Arguing that this was plain wrong can of course be considered "ivory tower", I'd call it "back to the spec". Same applies to IDs in representations: HTTP has a concept of an ID, it's called URI. If you build a remoting protocol on top of HTTP, why would you deliberately abuse it? You're not going to build a second SOAP, are you? ;) However, no one is going to prevent you from hacking the feature into the library, simply don't expect us to advocate breaking the abstraction :). Let's agree to disagree and move on… |
I knew this discussion would arise again. :-) Nice solution Manuel, will perhaps use it as well! |
By the way, how do you propose to resolve having access the entity ID without the rest of the URI on the client-side? URI parsing? Would be nice to have a pet-store sample app that shows us how to "go back to the spec", for illustration purposes as well as to ensure that spring data rest is useful for the real world... regards |
Do you have some news about this issue ? Indeed, I want to make a javascript client side application and it would be very nice to have this id returned in the response to use hateoas Rest web service directly. |
In the latest snapshots (and the upcoming version 1.1) you can configure whether or not you want an entity's ID exposed. The setting is not global, but it can be used (judiciously). |
Thank you, so I look forward to the next release. is there any release date sheduled ? |
Thanks Oliver for pointing me to this discussion. |
@deepakpol: Just go ask yourself, what is the ID of the resource you fetched? That's what you use as id on the client side. Everything else is baking server side knowledge into the client, which you want to avoid. REST is not about Javascript (frameworks). I'd be incredibly hesitant to let requirements (especially that contradict or work around the underlying principles of your remoting technology) your JS library imposes into the design of your server side implementation / representation. |
I would say, I totally agree about the REST Hateoas principle about the URI as ID but, with JS framework like angular or BackBone, the id in the model client side drives the http request (POST,PUT..) to create or update model server side. |
@deepakpol @fgaujous The latest SD REST 1.1 includes a configuration option in RepositoryRestConfiguration that allows you to expose the id value for a domain object. It's done on a case-by-case basis. |
@jbrisbin thank you, I will try it. |
@fgaujous I must admit I had a long discussion with @olivergierke as well regarding the Ids, which I thought need to be exposed for client side frameworks. I am not able to tell you anything about Backbone, but I am using AngularJS for 6 months now. In my first trials had serious issues without the Ids. Then I created a service, which takes care about the Id and resource handling. And I must tell you I don't need any Id in the service. |
@fgaujous Care to elaborate in how far its so terribly difficult for Angular/Backbone to work with URIs as IDs? Shouldn't it be totally opaque to the framework whether it uses a "1" or a "http://whatever.com/foo/1" or even an MD5 hash of the latter if you prefer to "hide" the URI structure and want to work with hex strings? I think it's terribly amusing that your client side javascript framework defines how to reference data. :) |
@olivergierke that's a matter of perspective. Others may see SD REST just as the data provider for the real product build in rock-solid Javascript. :-) |
@jhiemer Ok, Do you have somewhere an example with a service which takes care about the id and resource handling. ? |
@jhiemer - That's not the point. You've decided to use HTTP to access data, thus it's good practice to adhere to the concepts of it. And identity of resources is defined to be URIs in HTTP. You don't choose to ride by bike and complain about the missing steering wheel, do you? @fgaujous - That shows the entire dilemma… it's not "URIs as ids", a URI is an id… Unique Resource Identifier… I think it can't be more to the point. |
The main issue here is third party client side libraries that assume the URL for a resources is |
@scothis If I talk about backbone (and pretty sure other libraries too), it does provide a default implementation with some assumptions about URL creation. However, I don't think that is totally correct and restrictive either. The framework is not restrictive and you can always use links embedded in the resource to transfer the states by overriding the behavior if the service provider supports hypermedia. @jbrisbin thanks, I look forward to trying that out. |
@deepakpol library users will often take the path of least resistance, it's the lib's responsibility to make doing the right thing the easiest path. I didn't mean to sugest that the URI should be stored in a property with the literal name 'id', but that the URI should be used as the identifier for the resource. Having the URI in a resource twice would indeed be redundant. Having a link with a rel self is sufficient. A good library should be configurable to know where to find the ID, whether it be a property named 'id' or a self link. |
Hi Jon,
this is more a question than an issue report. What I was wondering about from the beginning on is, why the primary identifier in my case each Id of the entity is empty? In many client applications the primary identifier is important for application logic.
I did some short research, but I wasn't able to find some valuable information wether it make sense or not to include the primary id.
Could you explain it to me?
The text was updated successfully, but these errors were encountered: