Routing for a webapp in one place in one file e.g. yaml, xml or properties file to define the routing and urls for a webapp and connecting the urls with individual methods or functions seems like a good idea.Why doesn't Spring do it? The framework webapp2 is like that and easy to handle that way. A url routing scheme with a regex can look like good readability defined in yaml
handlers:
- url: /(amazonas.*|acre.*|alagoas.*|roraima-*|mato_grosso_do_sul*|pernambuco.*|bahia.*|rio_grande_do_sul.*|sao_paulo.*|goias.*|paraiba.*|piaui.*|ceara.*|amapa.*|tocantins.*|rondonia.*|sergipe.*|para.*|maranhao.*|rio_de_janeiro.*|rio_grande_do_norte.*|distrito_federal.*|espirito_santo.*|minas_gerais.*|parana.*|santa_catarina.*|rio_grande_do_sul.*)
script: br.app
- url: /obrigado.txt
static_files: static/obrigado.txt
upload: static/obrigado.txt
secure: optional
expiration: "24h"
- url: /ai/cat_tmpl/0
script: montao.app
Struts was also like that using xml for routing. Spring however does not have a good way to collect all your routing in one place. There's some in xml files, some as annotations (written directly above the method declaration in handlers) and some can be overridden with plugins such as the urlrewrite.
Why can't routing be gathered in one place for a Spring webapp? Wouldn't that be better design and a higher cohesion? It's also sometimes a problem that you can't have more than one webcontext for a webapp. It seems to be that the servlet specification doesn't allow more than one webcontext for a webapp and that it must be a bijection. Why?
Spring MVC is flexible enough to allow plugging another routing infrastructure.
You should take a look at springmvc-router.
Reverse routing is available as of Spring 4.1 (see SPR-5579) - but you can still vote for SPR-5757 if you'd like to see something like this in the framework.
Related
I'm investigating a Spring Boot project generated by JHipster and found out that its request mappings aren't done via web.xml nor via Spring's #RequestMapping but like so:
ServletRegistration.Dynamic someServlet =
servletContext.addServlet("someServlet", new SomeServlet());
someServlet.addMapping("/someUrl");
someServlet.setAsyncSupported(true);
My questions are:
Are there any reasonable advantages of dynamic registration instead of classic mapping?
Is it spring-boot's standard of registering mappings or it's just a will of jhipster's owner?
Is someServlet.setAsyncSupported(true) just another way of making response.setHeader("Access-Control-Allow-Origin", "*")?
Is there any reasonable advantages of dynamic registration instead of classic mapping?
Dynamic servlet registration Servlet 3+ way of registering servlets. In Servlets 3 you can avoid creating web.xml and configure application in pure Java. It gives you some advantages like compile time check if everything is fine there and what's more important since you do it in Java code, you can do some additional checks or conditions - for example register particular servlet only if environment property is set or class is available on the classpath.
It's not a replacement for #RequestMapping. In case of Spring Boot you will use it most probably when you want to register some 3rd party servlet - like Dropwizard Metrics servlet in case of JHipster.
Is it spring-boot's standard of registering mappings or it's just a will of jhipster's owner?
There are at least 2 ways of registering additional servlets in Spring Boot. See answers here: How can I register a secondary servlet with Spring Boot?.
Your own controllers you map as usual with #RequestMapping.
Is someServlet.setAsyncSupported(true) just another way of making response.setHeader("Access-Control-Allow-Origin", "*")?
Nope. For setting this header you use usually CORSFilter (read more: Enabling Cross Origin Requests for a RESTful Web Service). asyncSupported flag is used to make servlet able to process request asynchronously.
We are starting a new project using Spring MVC, and we would like to move away from annotation-driven request/url mapping. We wish to implement the following use case:
Use Case A
User enters a URL.
The request mapping handler retrieves a list of mappings (e.g. from the DB), and based on this dynamic list of mappings, it calls the relevant controller.
This is because we want to be able to do the following as well:
Use Case B
We want to load a new Controller (perhaps a new reports module) into the web app without having to redeploy or do a server restart.
We will map this new Controller to a URL and persist it somewhere (most likely the DB).
We would like the Controller to be registered in the Spring app context (managed by Spring).
We would then like to use this new Controller in the request mapping.
We've taken an initial look at the different ways we can implement this, but we are unsure of the best architecture/method to go about this route. A couple of questions:
For Use Case A, how do we implement this within the Spring MVC framework (or if it's possible)?
For Use Case B, is there a good framework or way to be able to do dynamically loading and registering of this for web applications? We've taken a cursory look at OSGI but it seems to be advisable for use in non-web applications.
For Use case A :
Instead of DB you can keep the url mappings in a property file and then use property place holder to initialize beans using xml configuration on context up. This way remaining inside the spring framework, you can avoid annotations.
For Use Case B :
Tomcat supports dynamic reloading of classes but that to of only non structural changes in class file. But this has memory leaks as well as it doesnt cleans up old instance of class loader rather it creates a new instance.
Its quite achievable using spring-mvc-router API.
Please check below link
url-action mapping & routing in Spring MVC 3.0
Here the URL can be configured to controller.method using .conf file, but this can be achievable using java configuration, and i haven't tried so far.
Also if xml configuration chosen, then check out the property 'autoReloadEnabled', but its not adviceable for production use.
Hope this helps!!!
From what I know of MVC outside of the Java world (PHP and Ruby on Rails), all requests are first sent to the front controller (or dispatcher... or boostrap, etc.), and the front controller looks to the request path pattern in the URL in order to determine what class/method should handle the request. In Java MVC, it appears that servlets are mapped with the url pattern in the deployment descriptor (web.xml), but the file extension and url pattern doesn't appear to be very flexible. Are there any Java MVC frameworks that use a front controller to read the request path exclusively to determine what classes should execute? Would it be fairly easy to hack Spring MVC to do this? Any examples? Thanks!
An example of one tool that works as you desire is web4j.
By default, it maps incoming URLS to the Action class whose package-qualified name maps in a fairly natural way the the incoming URL.
Example from its docs:
Request URL: 'http://www.blah.com/fish/main/member/MemberEdit.list'
Extracted part of URL: '/main/member/MemberEdit'
Maps (by default) to the Action: 'hirondelle.fish.main.member.MemberAction.java'
This is an example of how that particular tool performs the task. Since this is such a basic feature of web apps, I would imagine that nearly all such tools have similar mechanisms.
I am not a big user of Spring, but I can see from its docs that it has a number of ways of mapping requests to Actions :
SimpleUrlHandlerMapping
ControllerClassNameHandlerMapping
Java servlet mappings can also be by file extension.
Much like many non-Java frameworks, you could map all requests to a single servlet that then processes them but that tends to be discouraged in Java. It's certainly possible though.
If you want more REST-style URLs where you declare the mapping of path elements, you might want to look at the Spring MVC setup in Spring 3.0.
I agree the URL mapping is not very flexible but you can handle mapping with URLRewriteFilter
http://tuckey.org/urlrewrite/
For this purpose, the filter works almost like a controller.
Check out stripes:
http://www.stripesframework.org/display/stripes/Quick+Start+Guide
I've been looking at it as a possible upgrade from struts. There is an example on that page that is very similar to the web4j example given by John O.
I'm developing a web application using Spring MVC 3.0 and looking for a ready-made solution, if any, or a "best practices" reference for a url/action mapping and routing system that can achieve the following:
REST-friendly controller / method name to view mapping. The current mapping implementation translates the request to a view name, which may be problematic when using several parameters and is incompatible with REST urls
A service that accepts the name of a controller, a method and arguments values and renders the URL that's represented by them
Integration with Spring Security that can allow me to check for a given URL whether the current user is allowed to access it, so that I can decide whether or not to render a URL
A menuing system based on the above that can define menues composed of these actions and render them to page
Basically what I need is the ability to define URLs in one centralized place, so that changing a URL (during development; I'm aware of the don't-change-live-urls idea :) ) does not mean looking up and changing that URL in a zillion pages.
Any directions to such an existing solution / tutorial / guide would be great.
Thanjs
This is a feature I really miss in Spring MVC.
That's why I created the springmcv-router project, basically a port of PlayFramework's Router implementation in Spring MVC (HandlerMapping + HandlerAdapter).
I'm heavily using it in several real-world projects and the Router implementation itself is reliable.
Try using Spring Roo. It utilizes many best practices for spring MVC, and it has a scaffolding feature that automatically maintains a menu, jsp's and all the CRUD methods of a controller.
Setting up Spring Security with Roo is as simple as typing "security setup".
Hope this is helpful.
My Spring Dispatcher servlet url-pattern is /* (as spring MVC REST suggests)
Now all the request are resolved by this Servlet. even CSS/JS/Images also get resolved and handled by servlet..
So, Spring MVC tries to find controller.. :(
How to bypass this? Is there any standard way out of this problem??
& Don't want to change url-pattern to /rest/* (so, other static resources get accessed by /css/ or /js etc.)
You can map your controllers to a smaller set of URLS (i.e. /app/*), and then rewrite the URLs that your users actually see so that they don't even know about. Have a look at the mvc-basic webapp sample, particularly web.xml and urlrewrite.xml to see how this is done.
Map the Spring dispatcher to some subsection of the URL space, and use Tuckey to rewrite URLs the user deals with.
http://www.example.org/app/controller/action -> http://www.example.org/controller/action
Just a heads-up update on this: the default rewrite configuration as defined in the Spring sample did not work out of the box for me. The rewrite rules for stylesheets, scripts, etc. were still processed to the /app/* rule, and subsequently handled by the DispatchServlet, which is not desirable.
I had to add the last="true" attribute to the styles/scripts/images rules to indicate that other rules should not apply, and I had to use the FreeMarker Spring URL macro in any CSS/JS include paths.
Just in case someone encounters the same problem.