Closed yuranos closed 6 years ago
Hi,
so it's done on purpose assuming that path variable is an id
which is natural to assume for REST API.
If you have:
/abc/bookings:
/{bookingId}:
method generated will be getById
which is IMHO a bit better than getByBookingId
since we are returning Booking
object.
What we can improve is recognizing an id
as a path variable so we keep getById
in that case and we use your logic in all other cases.
Another thing I don't like is that generated method name depends on other parts of resource - /abc
in my example since without it generated method name will be getBookingById
. Maybe I miss some logic here.
@kurtpa can you enlighten us on the naming logic?
HI, @stojsavljevic . For your example, it doesn't make sense to call a path param bookingId, we can elaborate on that in README. My case is about something different. BookingRef is not the same as bookingId. I know it might not comply with RESTful conventions, but as with #211, it's all about adding flexibility. Unlike with some of my old PRs where I added new maven plugin params, and you rightfully stated that too much flexibility can be potentially a minefield, in this case, everything is hidden from a plugin user. Even with the extra verbosity that you mentioned in your example, I think it's better than having a confusing "update" naming for POST.
Another thing I don't like is that generated method name depends on other parts of resource - /abc in my example since without it generated method name will be getBookingById.
Sorry, @stojsavljevic , I didn't get it.
/abc
will never be taken into account. This name = name +
is a complete mess and I deleted it as part of the PR. That part of the code will only be called when index == splitUrl.length-1
, so it seems there's no need to append the name to itself.
I tested this on your branch:
/bookings:
get:
responses:
200:
body:
application/json:
type: Book[]
/{bookingRef}:
uriParameters:
bookingRef: number
get:
responses:
200:
body:
application/json:
type: Book
gives:
BookingController
public ResponseEntity<Book> getBookingById(BigDecimal bookingRef);
while this:
/customers/{customerId}/bookings:
uriParameters:
customerId: number
get:
responses:
200:
body:
application/json:
type: Book[]
/{bookingRef}:
uriParameters:
bookingRef: number
get:
responses:
200:
body:
application/json:
type: Book
produces:
BookingCustomerIdCustomerController
public ResponseEntity<Book> getByBookingRef(BigDecimal bookingRef, BigDecimal customerId);
And raml snippets are almost the same! Also, this:
/bookings:
/abc/{bookingId}:
will lead to different results but this:
/bookings/abc:
/{bookingId}:
So, the way resources are organized influences creation of controller and the name of methods. Don't worry, this is existing behavior, not something you break up. I pointed this out so anyone is aware.
What you want to change in your PR is the first case where you still get ById
suffix.
I will be perfectly fine if you add ById
only in case when path variable is exactly (but case insensitive comparison) resource name (singular) + id
. Basically, this is the line you want to change:
if (!StringUtils.isEmpty(peek) && segment.toLowerCase().contains(NamingHelper.singularize(peek))) {
And we need few tests to cover this issue :) Create something like Issue215RulesTest
using few cases like ones we just discussed.
@stojsavljevic , I don't know what we are doing differently, but using my branch I get a completely different result. For both RAMLs you provided, I get getByBookingRef method name and I also get the same controller name every time, BookingController.
@stojsavljevic , I added Issue212RulesTest
, please check. I understand the method names you provided, I think, but I still can't get how you generated BookingCustomerIdCustomerController
controller name.
Sorry again for the confusion with file names - I explained it in #217
But when it comes to method names (which is the subject of the issue) - I still see different behaviors.
And your tests confirm that (issue-212-2.raml
and issue-212-1.raml
).
When you have root resource /bookings
- generated method name is getBookingById
.
With something in front of /bookings
resource (in your test it's /customers/{customerId}
) - method name is getByBookingRef
.
@stojsavljevic , please check my last commit. I just realised that what I really didn't like and what was really confusing is the way the URL was reduced. I actually wanted to report it a long time ago, but now I think maybe we can simply fix it in scope of this ticket.
Just think of it: modelling RESTful contracts should be very neat and straightforward. The minimum URL should be something like resource/{id}. And there's simply no reason to call id
something like uri_int_param
.
To me getActionName
looks a lot clearer now.
What do you think?
Just the fact that there's only 5 tests failing in my last commit is telling me that the solution is pretty good and does not introduce a lot of distraction.
The code is more linear now and less cyclomatically complex.
And how about the old method name vs a new one:
getByBookingRef
vs getBookingByRef
I just realised that what I really didn't like and what was really confusing is the way the URL was reduced. I actually wanted to report it a long time ago, but now I think maybe we can simply fix it in scope of this ticket.
Can you give me an example? Do you need some more work for this?
Just think of it: modelling RESTful contracts should be very neat and straightforward. The minimum URL should be something like resource/{id}. And there's simply no reason to call id something like uri_int_param.
Agree that contracts should be neat and straightforward. But as we discussed, there more than one way to do things. Some people might use resource/{id}
and some resource/{resourceId}
. I'd like to have both cases boil down to the same generated code. I think that's true with your latest commit. Am I right?
To me getActionName looks a lot clearer now. What do you think?
Well.. It's not very clear but it was even worse before. So.. 👍
Just the fact that there's only 5 tests failing in my last commit is telling me that the solution is pretty good and does not introduce a lot of distraction.
That's definitely a good thing. Can we fix remaining test please?
And how about the old method name vs a new one:
getByBookingRef
vsgetBookingByRef
Much better indeed 👍
@stojsavljevic , you are right. With my latest commit both resource/{id}
and resource/{resourceId}
.
Unfortunately, I can't get any credit for that, because it's all under the hood of StringUtils.difference() :laughing:
Tests fixed. Give it a look, @stojsavljevic .
Hello, @stojsavljevic . Are you there? We haven't lost you for Xmas, have we?:)
Hi @yuranos
no, you haven't lost me for Xmas, I'm Orthodox and my Xmas is in January :) Actually, I'm working hard on the plugin - I'm working on a simplification as you can see in Project page.
I will try to merge your PR today, but as stated in #65, I will work more to consolidate naming before next release.
In
NamingHelper
:peek
can be empty and I'm sure it would be preferable for everyone to have"By" + StringUtils.capitalize(segment.substring(1, segment.length()-1));
As an example: For raml:
I'd rather have:
Then:
Now, there's another issue with the way
resource.getUri()
is built, but I will report it separately.