Restlet URL/path pattern mismapping - java

I'm developing a REST API using Restlet.
So far everything has been working just fine. However, I now encountered an issue with the Router mapping of URL to ServerResource.
I've got the following scenario:
GET /car returns a list of all cars
GET /car/{id} returns details about the car with id 1
GET /car/advancedsearch?param1=test should run a search across all cars with some parameters
The first two calls work without any problems. If I try to hit the third call though, the Restlet Router somehow maps it to the second one instead. How can I tell Restlet to instead use the third case?
My mapping is defined as follows:
router.attach("/car", CarListResource.class);
router.attach("/car/{id}", CarResource.class);
router.attach("/car/advancedsearch", CarSearchResource.class);
CarSearchResource is never invoked, but rather the request ends up in CarResource.
The router's default matching mode is set to Template.MODE_EQUALS, so that can't be causing it.
Does anyone have any further suggestions how I could fix it?
Please don't suggest to use /car with the parameters instead, as there's already another kind of search in place on that level. Also, I'm not in control of the API structure, so it has to remain as it is.

you need to add .setMatchingQuery(true); to that rout in order it to recognize that it is with a query at the end of it.
Router router = (Router) super.createInboundRoot();
TemplateRoute route1 = router.attach("/car/advancedsearch?{query_params}", MyResource.class);
route1.setMatchingQuery(true);
return router;
Mind that this pattern is with the exact specific order that you have determined in the route i.e. advancedsearch comes first and query_params comes after

I was able to solve this by simply reordering the attach statements:
router.attach("/car/advancedsearch", CarSearchResource.class);
router.attach("/car", CarListResource.class);
router.attach("/car/{id}", CarResource.class);

Related

Is it a good idea to call PUT from POST method

I have to automate certain operations of PUT/POST operation in my case, I have those endpoints already-in-place which will do their part.
My planning is to have another method which will drive this whole automation, consider this method as new POST endpoint which would gonna call each either POST and PUT endpoint from the same service which I already mentioned.
I will gonna call those existing PUT and POST based on input, if consider the input is new I will call existing POST and if given input exists in database I will going to call PUT.
Till I am good, But I have a question in my mind, Which is bugging me a lot that my new endpoint which is of POST is calling PUT as well as POST, I each method type has to do its type of operations only but here I am calling PUT as well as POST whereas my parent calling method type is POST.
I am not sure if I am working in right direction to achieve my use-case.
Please correct me in a different way.
Note - I am having Spring Boot application which would always need some endpoint to trigger any logic which I am talking about.
Update my question for better understanding.
I dont really know what you mean exactly. The HTTP methods are considered to do a specific task, but yet again its ok to use POST to update something - might be not best practice, but works. If you want to seperate the concerns (adding, updating), then just implement two different endpoints, one handling the creation the other one the update. The client (whether its a web-app or desktop app or whatever) has to handle this issue.

How to handle filtering in restlet resource

Hi i am pretty new to Restlet, and generally building web servers. I need to support filtering like this:
http://deviceip:port/resource?id=id
So far i know how to return a json message when user invokes different resources, based on my web server state. I would attach it to router, and add class which handles that resource. But how can i return only one resource from collection based on id? What i need to change in my class which is responsible from handling of that resource. Also how can i attach this resource to router? Any help is welcome, if you can write some code snippet to help me, that would be great.
Thanks
So as i understand you can approach to this in two ways. One is explained by link above and another one is using query. So basically you font have to create another resource like in the answer from link above, instead you can just extract query with this.getQuery()
and than call method getFirstValue("id"), which will return entered id.

Re-Route Requests without sending Redirect to client

I have a pretty simple purpose
URIs of form ->/random/* go to /*. For example /random/users goes to /users.
I don't wish to use redirect() to solve the problem.
I have a tried a few ways but not sure about implementation -
Intercept the request before it reaches the router. And change the URI somehow. I am trying to Override the onRequest method, but unable to proceed as I don't know the implementation. (possible issue with: should routing really be here?)
Have an entry in routes which is like /random/*, make it point to a controller method. From inside the controller call the router method again with the modified URI. Again here unable to proceed as stuck with implementation.
Double the routes file or put a regex in routes file. For each entry, copy it and append /random to it. I dont want to do this, since it makes the file difficult to manage. Last resort really.
Please help regarding how to implementation Point 1 or Point 2.
If there is any other much simpler way please help..
Add a new Random-controller and create an action which forwards the calls to the proper controllers.
Use the following route:
GET /random/:controller controllers.Random.handleRandom(controller:String)
Let the handleRandom-action forward the calls accordingly (with or without redirect). You can either do some reflection-magic to forward the call to other controllers, or use a if-then-else- or switch-clause.

Restlet routing nightmare?

Okay this is ridiculous: (or probably my design is :)
Here are the URLs that we are using:
/{projectName}/{wallName} - GET only: fetch all win conditions posted to the all
/{projectName}/WinCondition - POST a new Win Condition
/{projectName}/WinCondition/{id} - GET, PUT & DELETE
Now the funny part:
If the code is ordered as above the call POST: /myProject/WinCondition gets routed to the first route with wallName! And thus get a 405.
If I shift the /{projectName}/{wallName} to the bottom then it gets routed correctly!
Now here's what I know:
The default routing mode in Restlet
is MODE_FIRST_MATCH. I set that to
MODE_BEST_MATCH and the order of URLs
still matters! I am unable to access
the 'affinity' score to check what's
the problem/score. Matching mode is Template.MODE_EQUALS.
The question is then this: Do I have to be concerned with how I order the URLs in my java file???? That'll be scary, even from a maintenance point of view.
Any suggestions? Should I redesign my URLs?? But the 'structure' still tends to be the same leading to the same problem
"/{projectName}/{wallName}" and "/{projectName}/WinCondition" will obtain the same score for both FIRST_MATCH and BEST_MATCH so it is still the first in the route list that wins.
But this is really a side effect that you shouldn't get yourself into generally speaking. The problem is that it looks like you propose two routes to two different resource classes for the same URIs (such as "/myProject/WindCondition").
You should really consider redesigning your URIs to prevent such conflict. Here is a suggestion:
/{projectName}/walls/{wallName}
/{projectName}/winCondition
/{projectName}/winCondition/{id]
Otherwise, if relying on routes order scares you, it is possible to customize the default routing logic to take into account the target method for the scoring.

Overriding PropertyMessageResources in struts 1, connecting to the request

I have a Struts 1 application using standard Struts internationalization, with a property file and everything. I need to change a specific message for only a select group of users, so I want to extend PropertyMessageResources. However, I can't find a way to connect the current request (so that I know whether it's one of those select users) to the message lookup.
1) Is there a better way to get this functionality? I thought about putting logic in the jsp's, but that doesn't get some situations, like messages obtained through the validator.
2) Is there a possible way to connect the request to the various getMessage() methods of my extended PropertyMessageResources object?
Here's what I ended up doing:
In the login script, check if it's one of the select users, and add a special String to the Variant part of their Locale, and put it in the session as their locale.
request.getSession(true).setAttribute("org.apache.struts.action.LOCALE", new Locale(locale.getLanguage(), locale.getCountry(), customVariant);
In the overridden PropertyMessageResources class, in the getMessage(Locale,String) method, just check the locale passed in to see if it has the special variant. I made all my custom variants start with a "_", and I check the first character of the variant before looking it up (so as to not slow down other users).
If anyone has a better solution, please post it.

Categories