Skip to content
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

Allow multiple mappings on type and method level #186

Closed
iamiddy opened this issue May 27, 2014 · 9 comments
Closed

Allow multiple mappings on type and method level #186

iamiddy opened this issue May 27, 2014 · 9 comments
Assignees
Milestone

Comments

@iamiddy
Copy link

iamiddy commented May 27, 2014

@olivergierke While in Spring MVC @RequestMapping(value={"url1","url2"}) is allowed
The Spring Hateoas( 0.9.0.RELEASE) does not support this feature (multiple urls to one controller method) when building links with ControllerLinkBuilder linkTo() it internal call

public String getMapping(Class type) {
String[] mapping = getMappingFrom(findAnnotation(type, annotationType));
if (mapping.length > 1) 
{
  throw new IllegalStateException(String.format("Multiple class level mappings defined on class  %s!",type.getName()));
return mapping.length == 0 ? null : mapping[0];
}

the check ,if (mapping.length > 1) makes not possible for ControllerLinkBuilder to accommodate a feature(multiple urls) that springMVC already supports, any thoughts will be appreciated

@iamiddy iamiddy closed this as completed May 27, 2014
@iamiddy iamiddy reopened this May 27, 2014
@dschulten
Copy link
Contributor

I had a similar problem with method-level mappings and methodOn. In my case it would have been a good solution to use the first value to determine the link. Additional values are alternative mappings for the same method, they can be used e.g. for compatibility or flexibility. Using the first as 'canonical' could make sense, however.

@pcornelissen
Copy link

I just stumbled over this too. I just removed the class level mapping and created similar methods with it's own mapping and then just use one of those for the linkbuilder. It would be nice to use the approach suggested by dschulten!

@StephanBeutel
Copy link

Perhaps just include a parameter on withSelfRel() to specify which mapping should be used.

withselfRel() -> takes first mapping
withSelfRel(1) -> takes second mapping (count starts at 0)

Then just check if given index for mapping exists and throw exception if not.

@gregturn
Copy link
Contributor

gregturn commented Jan 5, 2015

@StephanBeutel Frankly, that doesn't sound intuitive.

@olivergierke, I would want to encourage the best practices. Making it easy to provide multiple mappings to one resource sounds like opening the door to things like versioning APIs (TL;DR Don't). If Spring MVC's @RequestMapping had the ability to declare one route "canonical" and other routes as secondary/whatever, then it would be clear what Spring HATEOAS should pick. Since Spring MVC doesn't have this, I prefer Spring HATEOAS working the way it is.

@pcornelissen
Copy link

I think it would be sufficient to just pick for example always the first one. As all assigned mappings would map to the same controller method, I see no real danger here.
When this behaviour is documented, then you can just rearrange the mappings if the link builder picks the "wrong" one.

@gregturn
Copy link
Contributor

gregturn commented Jan 6, 2015

Frankly, this issue can be easily worked around by splitting up the URLs into separate Spring MVC methods. Then you have the liberty to dub one "public String canonical()" and another as "public String legacy()". That would let you clearly embed semantics into the method names and not bury it in an arbitrary URL list inside an annotation.

@xelamitchell
Copy link

I'm having the same problem dealing with embeddable many-to-many sub-resources, for example Address which can be associated to either a User or a Company (the primary resources).

The functionality of managing the sub-resource is always the same: It has a resource associated to it (either User or Company) and performs the same operations: get an address, delete an address, create an address. AddressController has a mapping for eche specific resource endpoint:

"/companies/{resourceId}/addresses/{addressId}",
"/users/{resourceId}/addresses/{addressId}"

why would i need to create specific methods for a feature like this when the resource is not important for the service (addressId is not a composite but a unique id) and all I care about is building the correct endpoint representation for the client?

@pcornelissen
Copy link

OK, if you are afraid of a confusing behavior, you could also try to enhance RequestMapping by introducing a list of alternative mappings, so the regular value of the annotation becomes the "correct" answer and the alternatives are just for compatibility and not used for Linkbuilding.

Another solution would be to introduce an annotation that overrides whatever is configured in the requestmapping, so you can configure it without changing a spring mvc annotation.

odrotbohm added a commit that referenced this issue Jan 12, 2016
@odrotbohm
Copy link
Member

That's now fixed in master. We just use the first mapping defined if multiple ones are declared.

@odrotbohm odrotbohm added this to the 0.20 milestone Jan 12, 2016
@odrotbohm odrotbohm self-assigned this Jan 12, 2016
@odrotbohm odrotbohm changed the title Multiple class level mappings defined - AnnotationMappingDiscoverer-getMapping(Class<?> type) Allow multiple mappings on type and method level Jan 12, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants