I saw this in Grails documentation
static mappings = {
"/$blog/$year/$month/$day/$id"(controller: "blog", action: "show")
}
The above mapping would let you do things like:
/graemerocher/2007/01/10/my_funky_blog_entry
The individual tokens in the URL would again be mapped into the params object with values available for year, month, day, id and so on.
I have doubt is, if i have one more mapping just different is /$day/&month( above /$month/$day ). Even same path is valid for my new mapping also, then how it identifies which dynamic mapping and how to bind to params object.
You should never define 2 mappings like this:
"/$day/$month"(controller: 'one', action: 'index')
"/$month/$day"(controller: 'two', action: 'index')
A problem with that is that there is no way to ever distinguish between them for forward URL mappings. If a request comes into something like /5/6, there is no good way for the framework to decide which one to use. You could use named mappings which helps with reverse URL lookups, but the forward mappings would still be a problem. You need something that makes them unique in order for them to make sense. They could have a different prefix, or constraints but it doesn't make sense to have 2 separate mappings like those I described above. There is no way for the framework to make sense of those.
if there is no clear single mapping (e.g. overlap) the mapping, which is most specific, wins (least wildcards, most static parts). at last the order in your urlmappings decides.
pre-edit (see comments, wrong example):
see https://github.com/grails/grails-core/blob/master/grails-web-url-mappings/src/test/groovy/org/codehaus/groovy/grails/web/mapping/OverlappingUrlMappingsMatchingSpec.groovy
Related
Ive a method that takes an object. The object is dynamic and it can be constructed in 5 differents ways depending on how many children it has and which type of object it is. I want it to be clear how to build this object and also show which children types thay can be used together.
Example A:new Michael(id,name, Type.A, new Sara(id, name, ChildrenType.B));
Example B: new Sandra(id,name,Type. C, new Pheno(id, name,ChildrenType.D), new Leo(id, name,ChildrenType.E));
As i said before, the object is dymanic and can be build in different ways depending on which type the object has and how many children it has.
I thought that the best way to show all of this would be to have 5 different example bodys in swagger. But idk if it is possible? Is it and is this the best solution for this?
And im using java, if it makes any diff which languages i use.
Thanks!
You can define only one example per mime type.
However your can use externalDocs to redirect to another page with all your examples.
If you have a common interface for the payload, you can use a discriminator to choose the different concrete types that can be instantiated.
I am developing an MVC application which makes use of plugins. I need to support using Web API from those plugins. I have it working (including Dependency Injection with Autofac as well). However, it seems like Attribute routing is completely ignored from the class libraries (plugins or any other assembly). For example, I have a test plugin specified as such:
[RoutePrefix("api/cms/test")]
public class TestController : ApiController
{
When browsing to /api/cms/test, I get the following error:
"No HTTP resource was found that matches the request URI '[my site]:30863/api/cms/test'.No type was found that matches the controller named 'cms'."
When I remove "cms", it works because it is then using the default route. Obviously this is not adequate, because I will very likely have multiple controllers with the same name (in different assemblies) and therefore need a unique route to each of them.
I inspected the Route Collection in System.Web.Http.GlobalConfiguration.Configuration.Routes as well to confirm and the route is indeed missing.
Is there anyone who can tell me why the attribute routes are being ignored for class libraries and if there's a workaround?
EDIT
Thanks to Kiran for the comment about the Route attribute; I did notice my error with forgetting the [Route("")] attribute on the controller which is to be used along with the [RoutePrefix] attribute. I added that and now attribute routing works fine. However, I still cannot have 2 controllers with the same name, even though they are in different assemblies. After doing some research it seems that this is a known issue - not just with different assemblies, but different namespaces in general. I tried to implement a solution from here:
http://shazwazza.com/post/multiple-webapi-controllers-with-the-same-name-but-different-namespaces/
The problem with this is that now the DataTokens is null AND read-only! So it is no longer a viable solution to this problem. Hoping someone else has a solution to this problem.
EDIT 2
Thanks to Kiran for his mention about route constraints. However, that still doesn't solve my problem. What I am looking for is a way to allow multiple controllers to have the same name whether they be in separate areas, separate namespaces or both.. whatever.. The problem with this is that the underlying Web API implementation looks up controllers by name using an IDictionary<string, HttpControllerDescriptor> variable to store such information. You can see this if you look at the source code for DefaultHttpControllerSelector. So, at first I thought maybe I just need to inherit this class and override GetControllerMapping() because the calling code in the internal class, AttributeRoutingMapper doesn't care about the keys in that dictionary at all... it only looks at the values. So at first I thought I could override this and use the full name of the controller (including namespace) as the key, so we can get them all in there. However, it is not that easy.. for a couple of reasons, not least of which is the fact that AttributeRoutingMapper is not the only class to call GetControllerMapping().
So it looks to be a lot of work to get what I need done; if is it even possible at all. I will be starting a bounty; 100 points to anyone who can provide a fully working solution or who can provide enough info for me to start a solution myself.
From the error message, looks like the order of routes are not correct...looks like your request is being matched by a conventional route (ex: api/{controller}) rather than the attribute route...as you know route order matters...so make sure to have attribute routes register before conventional routes as they are more specific...
Also note that RoutePrefix attribute alone doesn't add routes to the route table, but the attribute Route does...
I am guessing you are hosting your application in IIS?
This really powerful feature of grails
def save(MyDomain model) {
model.save()
render ''
}
will parse the request body or params, run MyDomain.get(id), fill in the properties from the request body or params and save. That's a lot for this little bit of code.
How do I limit the properties to bind to model? Say I have an accountBalance property that is read only and I don't want a malicious user to be able to change their account balance.
Also, I want to have multiple actions that save a different subset of properties of MyDomain... say one action could be for a bank teller user that is making a deposit for the account holder. In this case the teller should be able to set accountBalance but not password.
I realize that an actual banking app wouldn't work like this, it's just an example.
I had other problems that led me to use command objects to bind data (see Grails fails to parse request when content type is specified during post). Any solution would also have to address that post. I imagine if the solution uses command objects then it will work, but if command objects aren't in the solution, then the request body problem has to be addressed.
Have not tried on an actual domain class but can you try using bindData instead of implicitly binding where you can particularly specify which property to exclude?
def save() {
//params - A Map of source parameters
//It can be params or any other representation of request body
//request.JSON, request.XML
MyDomain model = MyDomain.get(params.id?.toLong())
bindData(model, params, [exclude: ['accountBalance']])
model.save()
render ''
}
I suggest you take a look at the documentation about binding. There is a lot of information, in particular the section about security which is similar to your concerns. Looking at the fact bindData() allows you include/exclude properties you should be able to write any variation of your binding you need.
I understand that in MVC pattern and in REST services it is common to use URIs like /items/{id} but what is bad thing about using query parameters in the URI?
GET /items/{id} vs GET /items?id={id}
Further, lets say an entity has 'referenceId' field that points to some related (say parent) entity, and I need to create REST service to get all items for parent entity, which way is better:
GET(POST) /items/parent/{parentId}
or
GET(POST) /items?parent={parentId}
Will be grateful for insights that would help to resolve my subjective issues on constructing URLs for REST services.
I would use the following schemes.
/items/id
This uniquely addresses a resource of items with id id. We are not using parameters as a parameter to uniquely address this resource (as is the case with the other option). Just as
miguelcobain suggests.
/parent/id/items
Here id is an id to uniquely address a resource of parent and from those we collect/retrieve the items it references. From what you have said in the question it seems that parent references multiple items, like a container or collection.
The convention I use for this is to narrow down the scope going from left to right. Therefore in case items could be active or inactive. Thusly items have a property or attribute to be active or inactive. Narrowing down on this I get the following scheme:
/items/active
/parent/id/active
For your first question:
/items/{id} should retrieve a single resource with the specified id or 404 if it doesn't exist.
/items/?id={id} should retrieve an array (even if only one in the array) because you are querying the collection.
For your second question:
I agree with #miguelcobain's assessment - if the item is a specific resource/entity, just use the proper resource path to retrieve it.
To make this easier on the consumer, create a link header with rel="parent" and/or include the uri in the child resource. For an example of link headers, see GitHub's pagination api.
Of course, REST principles don't care about aesthetic details on URLs. It just imposes that every resource should be uniquely addressable.
Furthermore, using the query parameters to uniquely address something "kind of" violates the semantics of a "parameter", doesn't it? A parameter should be something optional, something additional and parameterized. Something like a detailed search on a collection of items, for example.
What you wrote may make sense in some cases. It depends.
In your example, is the item really a resource? If not, you could just do GET(POST) /parents/{parentId}.
If parent is, say, a boolean, and you want to search the items that have parent equals to true, then using the parameters makes sense. But since you're explicitly saying that you want a parent with a specific id, I assume that parent is a resource itself and I would uniquely address that resource using your option 1.
I hope I made myself clear.
It seems to me there are no rules to follow.
items/{id} - this convention is suitable for GET item by given id. If user doesn't provide id then it returns 404 status code.
items/id={id}&name={name} - this type of convention is suitable for search multiple items by given criteria. If no items are found, it is not a 404 situation, you simply say "I successfully found nothing matching your search criteria"
I'm very new to grails (day 2).
First, I find it hard to find easily browsable resources (the documentation is very raw, and the tutorials are spread out and only show 'hello world' types of examples ).
I've set up my domain class with a relationship to other data types.
class ShopCategoryPage{
//some stuff
ProductProcedure procedure;
ProductCategory category;
//some stuff
}
In my controller, I am getting a category id and a procedure id as parameters, and I am trying to get the ShopCategoryPage associated with those parameters.
How do I "find" them? I tried passing the ids as procedureId or procedure_id, I tried passing a ProductProcedure object generated by findById ...
I'm not sure how to find by a property that is not of native type.
First, I find it hard to find easily browsable resources (the documentation is very raw,
and the tutorials are spread out and only show 'hello world' types of examples ).
In my opinion the documentation is great, perhaps we're using different docs. I use:
Grails Reference Documentation
Grails JavaDoc
GDK, i.e. methods Groovy adds to Java classes
If that still isn't satisfactory, I highly recommend the book "The Definitive Guide to Grails". I believe "Grails in Action" is also very good, but haven't read it. For learning Groovy, "Programming Groovy" is a great book (albeit a little out of date).
In my controller, I am getting a category id and a procedure id as parameters, and I am
trying to get the ShopCategoryPage associated with those parameters.
The easiest way (though not the most efficient) is to use the dynamic finders.
// First of all load the ProductProcedure and ProductCategory
// I'm assuming here the request params are named 'procedureId' and 'categoryId'
ProductProcedure productProcedure = ProductProcedure.get(params.procedureId.toLong())
ProductCategory productCategory = ProductCategory .get(params.categoryId.toLong())
// Now get the ShopCategoryPage associated with these. Replace 'find' with 'findAll'
// if there could be multiple associated ShopCategoryPages
ShopCategoryPage shopCategoryPage = ShopCategoryPage.findByProcedureAndCategory(productProcedure, productCategory)
A shortcoming of this approach is that it will cause 3 SELECT statements to be executed. If you're only interested in the shopCategoryPage returned by the last query, you could load this in "one shot" using HQL or a criteria query instead.
You should never use findById since it'll bypass the id-based 2nd-level cache and only use the query cache, which is a lot more volatile. Use get() instead.
Having said that, there's two ways to do this. One is to use get():
def shopCategoryPage = ShopCategoryPage.findByProcedureAndCategory(
ProductProcedure.get(params.procedureId),
ProductCategory.get(params.categoryId))
(use the appropriate param name for the two ids)
or using an HQL query (or a criteria query) to fetch the instance in one query instead of 3:
def shopCategoryPage = ShopCategoryPage.executeQuery(
'from ShopCategoryPage p where p.procedure.id=:procedureId and p.category=:categoryId',
[procedureId: params.procedureId.toLong(), categoryId: params.categoryId.toLong()])[0]
I agree, the easiest way is to use an dynamic finder.
In addition to 'The Definitive Guide to Grails' by Rocher and Brown, I suggest the IBM developerWorks track 'Mastering Grails' by Scott Davis.
http://www.ibm.com/developerworks/views/java/libraryview.jsp?site_id=1&contentarea_by=Java&sort_by=Date&sort_order=1&start=1&end=19&topic_by=&product_by=&type_by=All%20Types&show_abstract=true&search_by=mastering%20grails