SPRING MVC controller annotations vs xml - java

For new project, I was searching for which framework is to be used. I looked for the updates for existing frameworks.
I found it very intresting about Spring MVS controller, that in the controller itself you can now define which URL you want to hit. The best thing is that you do not need to rewrite url, that kind of feature is also there, i.e., you can give directly the url like:
\users\amit\stores\store1
Earlier I had to write url rewriting for making it this way, and actual url used to be like:
\StoreDetails?user=amit&store=store1
I found it very good. But on second thought, if I compare, if I start putting the urls in controller itself, will not it make a little difficult to maintain after say 1 year, when I have so many modifications done on the project and at times, the url given to Controller turns not related to the name of the Controller.
For example in above example, I might want to search for storedetails, but by url i would be searchin in StoreController etc.
What you guys suggest is good practice, to go with xml or to go with annotation based.
If you guys using the annotation based, do you face any issue?
Thanks & Regards
Amit

Spring MVC implements a lot of predefined conventions. For example if you do not explicitly define #RequestMapping on controller it will map it to url similar to controller name. For example if you controller is named Users it will be automatically mapped to url users. If then you rename your class to Customers it will be automatically mapped to url customers.
The same happens with methods.
The big question is whether you really want this. Typically you do not want your internal changes (including class renaming) directly and automatically affect API your provide.
If you choose to define mappings explicitly try to organize your project using certain convention that will simplify on-going support in future. You can also use public static final Strings in annotations. All URL dependent strings can be stored in one class, for example:
public interface Mapping {
public final static String USERS = "users";
public final static String PERMISSIONS = "permissions";
}
#RequestMapping(Mapping.USERS)
public UserController {
............
}

I would stick with annotations they are very simple to define and its pretty easy to discover the appropriate method from a view using a good IDE. They key is to search the entire project for a given URL string.
So for example, if I had the following jsp.
Store Link
I would just use the IDE's search feature (in Eclipse > File Search) to find /store/products/ which would most likely contain the controller in my search results. If your crafty with IDE search features the annotation mappings are really a non issue.

Related

List of all mapped RequestMapping values

Does Spring 4 keep an internal record of the mappings that are specified with #RequestParam? I am looking for a list of these mappings.
For example, if I annotate a method with:
#RequestMapping(value = "/myname", method = RequestMethod.POST)
I would want a list with myname.
I looked around a bit and I know about the Spring MVC Router project but I am simply looking for a method call that would return the mappings. Or alternatively, a list of all the paths registered with <mvc:view-controller/> would work too.
Background:
We have a business requirement to create public areas on our web application, similar to the tumblr model where you can have myname.domain.com and access an area created by that user. However, our method is using domain.com/myname since programmatically creating the former was not simple (would need to monkey with DNS/web server config files).
We extended GenericFilterBean to do this, but I want to make sure that when searching for 'myname,' the application can ignore actual pages (or more specifically, views) on the site. We want the front-end validation to disallow existing page names.
I think your question was already answered in here. This is a very good answer.

Good Idea to do Spring Validation in Domain Objects Builder?

I am writing some helper code to add builders to my domain model using the Builder Pattern. I have the basic portion of the code built, but I want to added another build method that will validate the newly built object. I envision this new method would accept a class to match up with the groups in my bean validation. Therefore, when I get the object back from the builder I know it is a valid object for the state I want. I have two questions concerning this approach.
First, does this sound like a good approach? I have not seen anything on the net about doing this, but I think it would be a good idea to have it in the builder.
Next question, What is a good way to get a validator into the builder? Should I try to auotwire it in or something else?
Using the builder pattern is a nice way to construct objects, so it should work well for your purposes. You said you want to add another build method. Is this implying that you would have 2 build methods - one that validates and one that doesn't? I would only have one method so you can be sure your object validates.
For how to validate, the Spring docs discuss validating using JSR-303 http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/validation.html
Just something to keep in mind as you're building a Spring app. Consider if grails might be something of interest to you. One part of it is domain object validation and it has capabilities to build objects for testing that will validate. Obviously you would want to use more features than just that if you're going to use grails, but just wanted to note it.

How to determine JAX-RS resource paths programatically?

Suppose I have a set of JAX-RS locators and sublocators, like the following:
#Path("/users")
public class UserListResource {
#Path("/{id}")
public UserResource getCustomer(#PathParam("id") int id) {
// Find and return user object
}
}
public class UserResource {
#GET
public String get() {...}
}
For example, a UserResource object with the ID 5 would have the path "/users/5". In my system, I have several different resources.
Now the question is: How can the server figure out the path of a given resource? Can I do this programmatically via some JAX-RS API or do I have to implement code that uses reflection? (I know how to do the latter, but would prefer the other approach.)
At the point when I need to know the path, I do not have a request object at all. For example, I have a timer which does some background processing, then changes some entities in the domain model, then informs all clients about the changed entities (including their paths).
I know that within the scope of a request, I can inject a UriInfo object that provides this, but I need to know the path in advance (to inform clients of a change that did not necessarily happen through the JAX-RS resource).
I don't want to repeat the path information in another place, and I also don't want to have a set of path fragment constants for each resource type (in this case "/users" and "/{id}").
As I read your question, you need to build a URI knowing only the resource class and the id parameter.
It can be done using the UriBuilder class as in:
UriBuilder builder=UriBuilder.fromResource(UserListResource.class);
URI uri=builder.path(UserListResource.class,"getCustomer").build(5);
It uses reflection under the hood, so it is not so easy to refactor, but it is all it is available at the moment.
Overall, be aware that something sounds rather strange with the architecture of your application. It's hard to put a finger on, but the pattern of questions you are asking is raising a number of red flags about how you're going about this. Be aware that if you are seeking to create a RESTful API to your application that you may need to stop, take a few steps back, and rethink what you are trying to do.
To your explicit questions…
Now the question is: How can the server figure out the path of a given resource? Can I do this programmatically via some JAX-RS API or do I have to implement code that uses reflection? (I know how to do the latter, but would prefer the other approach.)
The server knows the path, as that's always supplied by the user and is used to navigate through the collection of resource classes that make up your application. If you need a UriInfo instance for a particular call, you should inject it as part of that specific call:
#GET
public String get(#Context UriInfo info) {...}
Any information required from the outer context (e.g., what the resource's ID is) is best passed in during construction. You can reparse it out of the URL (obtainable from the UriInfo) again, but that's probably the wrong approach.
Otherwise, if you're doing something much more complex then you need to be more specific in your question.
At the point when I need to know the path, I do not have a request object at all. For example, I have a timer which does some background processing, then changes some entities in the domain model, then informs all clients about the changed entities (including their paths).
I know that within the scope of a request, I can inject a UriInfo object that provides this, but I need to know the path in advance (to inform clients of a change that did not necessarily happen through the JAX-RS resource).
How are you going to have the clients be informed? There's normally no mechanism to push messages from the server to the clients, and clients are typically firewalled so that they can't directly host a service.
Theoretically, you could associate (explicitly, by URL) each resource with its own RSS feed to which a client could listen to if they chose. You wouldn't be able to force clients to listen, but you could give them the option to do so. If you go this route, you don't need to know the UriInfo “ahead of time” as the location information will be present at key times (i.e., at resource creation) and afterwards you're just referring to something that you have control over.
But that's just one way to do it and it adds a lot of complexity; you'd only do it if it was critical to your application. It's often simpler to just have clients poll from time to time. (Note that some sorts of modifications are inherently very destructive; particularly altering the ID or deleting the resource. Don't expect things to cope smoothly with those.)
I don't want to repeat the path information in another place, and I also don't want to have a set of path fragment constants for each resource type (in this case "/users" and "/{id}").
Tough. Repeating information in multiple places, provided you draw it consistently from a single source, is a common practice. There's nothing actually wrong with it.
As I understand your question, you want to know the path as the request is coming in but before it hits your resource; are you open to using Servlet Filters?
JAX-RS specific filters are only supported in 2.0
For the record: after I had posted the question, I thought about our architecture a bit more and came to the conclusion that sending URLS is not as useful as I thought. The application has to know some details about the application structure anyway:
Continuing the example above: even if the client did not know the URL pattern for individual users, it must assume that there is a list of users and know its URL; it also has hard-coded knowledge what dialog to display for editing a user etc.
So all in all, attempting to tell the client (most) URLs it needs is not worth the effort. Instead, we decided to go with a custom API definition file which includes data about the resource contents and their URL scheme. This file is used to generate the following:
the server-side resource classes with the correct JAX-RS annotations
a URL scheme specification document for other developers to code against
classes for our own client (including the URL know how, e.g. user with ID 5 has the URL ...), so we don't have to worry about inconsistencies between our client and server.
This approach has the following advantages:
The need for the server to figure out the URLs from the annotations vanishes, as the client can now do that on its own once it receives a notification that includes the object ID.
We don't have to worry about inconsistencies between our client and the server, as all information is drawn from a single source.
We have one source for the API definition under version control which can be used to verify backwards compatibility with older releases.
Note:
I would probably not claim that the resulting API stays "faithful" to the idea of RESTful webservices, but it works for us and the elements that it borrows from "actual" REST architectural style should make the API clearer and easier to learn than a traditional contract-first webservice.

Can a spring mvc action method return both a model to a view or xml or json?

For a web application, I need to return a model to a view.
For a mobile application or API, I want to return xml or json.
Is it possible to do all of these using a single controller method, or do I have to duplicate this and create seperate API controller's etc?
With Spring MVC 3.x you can do this with just the one controller method. The trick is to wire up the appropriate ContentNegotiatingViewResolver in your Spring config. You can configure it to return the desired content type based on file extension and/or requested mime type.
It works best for methods that only add a single model attribute to the Model, otherwise the JSON/XML starts to get a bit ugly.
I often find its simpler/nicer to implement separate controller methods for my web service requests, as you can better control the format of the JSON/XML and the code is easier to maintain in the long term.
EDIT: Just to qualify my comment above, I find that complex JSP pages where there might be up to 5-10 model attributes added to the page, that the resulting JSON tends to be quite messy and you usually find you only really want 1-2 of those in the JSON. OTOH, simple pages with 1-2 models added work quite well.

How should I handle url routing in my application?

I'm building a web app with custom components. I need a way to route requests to class / methods, is there any standalone java library that can achieve that (in a sexy manner [1]) ?
[1] read : no xml!
In Spring WebMVC 2.5/3 you can do it all with annotations. The obvious downside is that of course annotation values have to be compile time constant, so you can end up with some effectively hardcoded URLs. If you go all-in with autowiring, basically the only XML is a couple lines to create the servlet, turn on the autowiring + package scanning, and possibly specify the view resolution strategy.
e.g.,
#Controller
public class WebController {
#RequestMapping(value="/pages/Home.htm", method=RequestMethod.GET)
public ModelMap buildHome(#RequestParam("foo", required=false) String foo){
return fillInHomePageData(foo);
}
In a degenerate resolution strategy it could, for example, then automatically go looking for jsp/pages/Home.jsp and build it with the data you returned.
You could take a look at Reflection, it is rather sexy and does not require XML.
What it can do that it instantiates classes to route to based on input.

Categories