{"id":10498,"date":"2014-04-09T14:50:55","date_gmt":"2014-04-09T09:20:55","guid":{"rendered":"http:\/\/www.tothenew.com\/blog\/?p=10498"},"modified":"2016-12-19T15:31:55","modified_gmt":"2016-12-19T10:01:55","slug":"customizing-url-formats-in-grails","status":"publish","type":"post","link":"https:\/\/www.tothenew.com\/blog\/customizing-url-formats-in-grails\/","title":{"rendered":"Customizing URL Formats in Grails (Making your URLs case insensitive)"},"content":{"rendered":"<p>When I started working on Grails I quickly noticed one caveat in its URL patterns. I wonder why on the Earth anybody would want such camel casing in URLs. Misreading the case sensitive nature of a Grails app URL can lead to broken links and 404 errors. That means you need to be careful when playing with how your URLs look like.<\/p>\n<p>For example:<\/p>\n<blockquote><p>http:\/\/localhost:8080\/myapp\/someLong\/someAction<\/p><\/blockquote>\n<p>works perfectly fine.<\/p>\n<p>But when I entered following URL patterns<\/p>\n<blockquote><p>http:\/\/localhost:8080\/myapp\/somelong\/someaction<br \/>\nor<\/p>\n<p>http:\/\/localhost:8080\/myapp\/SomeLong\/SOMEACTION<\/p><\/blockquote>\n<p>I get a <strong>HTTP Status 404<\/strong> that is <strong>&#8220;Page Not found&#8221;<\/strong> message.<\/p>\n<p>It does not matter what part I write in lower case it will just throw same HTTP Status code.<\/p>\n<p>The culprit here is routing engine of Grails. It&#8217;s configured to use the default settings. And how does Grails do that? Simply by implementing the <strong>grails.web.UrlConverter<\/strong> interface in a class named <strong>grails.web.CamelCaseUrlConverter<\/strong>. But as always this is just a convention not a requirement. So I went ahead and changed this by plugging in a new behavior or converter.<\/p>\n<p>So I created a new converter named <strong>LowerCaseUrlConverter<\/strong>. The name need not contain <strong>UrlConverter<\/strong> suffix, it&#8217;s here just to tell us that it implements some<br \/>\n<strong>UrlConverter<\/strong>. So here is the code:<\/p>\n<p>[sourcecode language=&#8221;java&#8221;]<br \/>\npackage com.myapp.utils<\/p>\n<p>import grails.web.UrlConverter<\/p>\n<p>class LowerCaseUrlConverter implements UrlConverter {<\/p>\n<p>    @Override<br \/>\n    String toUrlElement(String propertyOrClassName) {<br \/>\n        if (propertyOrClassName) {<br \/>\n            \/\/ If there is some class name or method name in url then convert it to lowercase.<br \/>\n            propertyOrClassName.toLowerCase()<br \/>\n        } else {<br \/>\n            \/\/ Else return default name.<br \/>\n            propertyOrClassName<br \/>\n        }<br \/>\n    }<br \/>\n}<br \/>\n[\/sourcecode]<\/p>\n<p>Now put this class in <strong>src\/groovy<\/strong> folder because it&#8217;s a Groovy file named <strong>LowerCaseUrlConverter.groovy<\/strong>.<\/p>\n<p>Next is to configure this bean so that Grails knows it needs to use new implementation of <strong>grails.web.UrlConverter<\/strong>, so that other parts of Grails can generate<br \/>\nlowercase URLs from its <strong>g.createLink()<\/strong> and <strong>redirect()<\/strong> and other methods.<\/p>\n<p>So open up <strong>grails-app\/conf\/spring\/resources.groovy<\/strong> file, and put inside <strong>beans<\/strong> closure this line:<\/p>\n<p>[sourcecode language=&#8221;java&#8221;]<\/p>\n<p>&amp;amp;quot;${grails.web.UrlConverter.BEAN_NAME}&amp;amp;quot; (com.myapp.utils.LowerCaseUrlConverter)<\/p>\n<p>[\/sourcecode]<\/p>\n<p>And that&#8217;s all we need to do. Now we are good to go with all lowercase URLs<\/p>\n<blockquote><p>http:\/\/localhost:8080\/myapp\/somelong\/someaction<\/p><\/blockquote>\n<p>You can even check it with some more combinations like:<\/p>\n<blockquote><p>http:\/\/localhost:8080\/myapp\/Somelong\/Someaction<br \/>\nhttp:\/\/localhost:8080\/myapp\/someLong\/someAction<\/p><\/blockquote>\n<p>or if you are crazy enough and gone nuts you can also try this:<\/p>\n<blockquote><p>http:\/\/localhost:8080\/myapp\/SoMeLoNg\/sOmEaCtIoN<\/p><\/blockquote>\n<p>One last thing.<br \/>\nI didn&#8217;t tell you about one more class that Grails has up its sleeves. And that&#8217;s the <strong>grails.web.HyphenatedUrlConverter<\/strong> class. You can guess by name what it does.<\/p>\n<p>One word of caution: You can&#8217;t have more than one implementation of <strong>URLConverter<\/strong> in <strong>grails-app\/conf\/spring\/resources.groovy<\/strong> file. However default one will always work regardless if you provide your implementation or not!<\/p>\n<p>Now I feel safer with my URLs&#8230; \ud83d\ude09<\/p>\n<p>Manvendra Singh<\/p>\n<p>My LinkedIn<\/p>\n<p>@Manvendra_SK<\/p>\n","protected":false},"excerpt":{"rendered":"<p>When I started working on Grails I quickly noticed one caveat in its URL patterns. I wonder why on the Earth anybody would want such camel casing in URLs. Misreading the case sensitive nature of a Grails app URL can lead to broken links and 404 errors. That means you need to be careful when [&hellip;]<\/p>\n","protected":false},"author":70,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":4},"categories":[7],"tags":[],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/10498"}],"collection":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/users\/70"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/comments?post=10498"}],"version-history":[{"count":0,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/10498\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/media?parent=10498"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/categories?post=10498"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/tags?post=10498"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}