Managing custom Acccept header in Spring MVC - spring

I have a RESTful web service developed using Spring MVC and without any configuration I can return objects from my #ResponseBody annotated controller methods that get serialized to JSON. This works as soon as the Accept header in the request is not set or is application/json.
As I'm getting inspired by the GitHub API specification, I wanted to implement custom mime type for my API as GitHub does, for example: application/vnd.myservice+json. But then I need to tell Spring MVC that my controllers can provide this mime type and that it should be serialized by Json (i.e org.springframework.web.servlet.view.json.MappingJacksonJsonView class).
Any idea how to do it?

You can probably do exactly what is being done with org.springframework.http.converter.json.MappingJacksonHttpMessageConverter. Since it is not a final class, you can derive your converter from this one this way:
class MyCustomVndConverter extends MappingJacksonHttpMessageConverter{
public MyCustomVndConverter (){
super(MediaType.valueOf("application/vnd.myservice+json"));
}
}
then register your converter this way:
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="MyCustomVndConverter "/>
</mvc:message-converters>
</mvc:annotation-driven>
It should just work with these changes

Related

Organising View in Spring MVC in real enterprise based application?

I am learning Spring MVC framework, and created a simple "Hello world" kind of web-application using Spring MVC framework.
My controller code is like this:
#Controller
public class SimpleController {
#RequestMapping("/welcome")
ModelAndView handleIncomingWelcomeReq() {
ModelAndView mw = new ModelAndView("WelcomePage","welcomeKey","WelcomeKey's value!");
return mw;
}
}
The spring configuration is:
<beans>
<context:component-scan base-package="com.example.controller, com.example.util"/>
<bean id="viewResolver1" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix"> <value>/WEB-INF/</value> </property>
<property name="suffix"> <value>.jsp</value> </property>
</bean>
</beans>
The code is straightforward, for /welcome , handleIncomingWelcomeReq() gets invoked and welcomePage.jsp is returned to the client.
For this simple application, we need to specifically mention the view page which it returns. Now my question is:
In real enterprise web-applications, how do we organise the view / page which gets returned for matching url. Wouldn't the spring configuration get too big, because we have to specifically mention the page which gets returned for each incoming url.
Is this the way Spring MVC builds the real life enterprise web application. Each page specifically mentioned in the spring configuration page?
Any inputs on this which help clarify this really appreciated.
The responsibility of defining the page flow specifically lies on individual controllers and views; for instance, you usually map a web request to a controller, and the controller is the one that decides which logical view needs to be returned as a response. This is sufficient for straightforward page flows, but when your application gets more and more complex (real enterprise web-applications) in terms of user interface flows, maintainance becomes a nightmare. If you are going to develop such a complex flow-based application, then Spring Web Flow can be a good companion. Spring Web Flow allows you to define and execute user interface flows within your web application.

Spring MVC interceptor

I need inputs related to Spring MVC, I have a URL to which a client will send a post request with an xml as the pay load. I plan to have a controller method which maps to the requested url, I want that xml to be validated/converted to an object using jaxb before controller method is executed. And also, the controller method should have only the object as the parameter to its methods and no httprequest etc.
So, how do I achieve this? Will interceptor be helpful? If yes, how will it be done?
I plan to use Spring 3.
Simply use #RequestBody in conjunction with #Valid on a method argument and that is all you need.
public void myRequestHandlingMethod(#Valid #RequestBody YourJaxbObject jaxbObject) { … }
I strongly suggest you take a look at the Spring reference guide

Accessing HttpServletRequest during DaoAuthenticationProvider authenticate in Spring Security

I need to access the HttpServletRequest object from within my DaoAuthenticationProvider in Spring security.
The security component extends the DaoAuthenticationProvider and we override the authenticate method to perform some custom authentication / validation. The additional check is required to validate user's ip-address which comes in the request url as a query string parameter (Ex: http://domain.com/context?ip=192.168.0.1).
The current approach I am trying is to make use of RequestContextHolder thread-local and get the http request in my custom DAOAuthenticationProvider.
Some other solutions that I read here and on spring forums seems to suggest to inject AuthenticationDetailsSource, use of custom-filter and other steps which I don't understand due to being new to spring security.
We would have different web applications which use the same security component to perform authentication.
Can someone please point me in a correct direction or help me with any approaches implemented previously ?
You can use RequestContextHolder and it effectively contains the same request, though Spring Security will usually wrap the incoming request, so you may get a different reference depending on whether you place the RequestContextFilter before or after the Spring Security chain (note that you could easily check this yourself by comparing the value returned from RequestContextHolder with the request in an application controller).
It is also relatively easy to inject a custom AuthenticationDetails as you mentioned:
package com.mycompany;
public class MyWebAuthenticationDetailsSource implements AuthenticationDetailsSource {
public Object buildDetails(Object context) {
return ((HttpServletRequest)context).getParameter("ip");
}
}
Then use
<bean id="ads" class="com.mycompany.MyWebAuthenticationDetailsSource />
<bean id="formLoginFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
<property name="authenticationDetailsSource" ref="ads" />
<property name="authenticationManager" ref="authenticationmanager" />
</bean>
and add this as a custom filter as described in the reference manual. In 3.1 the namespace supports this directly in the form-login element. Authentication.getDetails() will then return the value of your "ip" parameter.
Note that you probably shouldn't be using 3.0.4, as it has known security vulnerabilities.
Also, can you explain how the "ip" parameter is being set?
You can add Spring's RequestContextFilter in your web.xml. This way, attributes will be saved on current thread on every request. Then, you can get original HtttpServletRequest:
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
HttpServletRequest request = attributes.getRequest();

How to set content-length after a view is resolved using spring mvc?

We're using Spring MVC (3.0.5) for an API we are building. However, we have discovered that the application does not always return a content-length in the response header. Why I haven't figured out as yet. We can not manually set the content-length in the controller (request.setContentLength(x)) because we only use a subset of the data we get with the controller in our Freemarker view. So basically what we need is to calculate and set the content-length after a view has been resolved/compiled and just before it is actually sent to client.
Are there any common ("good praxis") ways to do this? Or even "ugly" ways?
Intercept your requests by implementing the HandlerInterceptor interface. The afterCompletion method runs after the view is resolved, so you should be able to set the value there, as that method's signature passes the HttpServletResponse. Configure thusly:
<!-- Configures Handler Interceptors -->
<mvc:interceptors>
<bean class="com.myapp.web.interceptor.MyInterceptor" />
</mvc:interceptors>
Here's some basic code:
#Component
public class MyInterceptor implements HandlerInterceptor {
}

Spring: Global Path Variable or Request Parameter without Controller

I have a Spring Boot & Spring Security application running, which should now get multi tenancy support.
I'd like to keep things as simple as possible. Though I'd like to determine the the database by path variable or request parameter. (the Apache Web Server in front of the Spring Boot app will handle that, i.e. it maps from subdomain to either path variable or request parameter).
Now I need a way to grab the first path variable (or a specific request param) before Spring calls the controller, and of course the value must be stored somewhere, so I can access it when I need to choose the right database.
So either (depending on what's possible / easier)
http://localhost:8080/customer1 (which I'd prefer) or
http://localhost:8080?_customer=customer1
should simply call the #Controller with #RequestMapping("") and the value customer1 should be stored somewhere for that request.
I know that 2. might be simpler, because it will already hit the right #Controller, but I'd prefer 1. somehow.
Thank you!
EDIT:
I just recognized, that HandlerInterceptor doesn't work as expected, because Spring Security always handles the requests first. Though I need an Interceptor that handles it before Spring Security kicks in.
You can make use of org.springframework.web.servlet.HandlerInterceptor. Implement the logic to store the values in request via preHandle method.
Configure it in spring config file as below
<mvc:interceptors>
<bean class="com.blah.interceptor.SomeInterceptor"/>
</mvc:interceptors>
In case requests are to be intercepted based on path, use below config instead
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/customer1" />
<bean class="com.blah.interceptor.SomeInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>

Resources