File size restriction upon form submission - spring-boot

Is both approaches the same when it comes to application processing the request?
spring.servlet.multipart.max-file-size
Or just validating the file in my controller (or using form validation using #Valid and implementing Validator, etc).
Does both approaches check file size AFTER application has fully received the request? Or spring.servlet.multipart.max-file-size sets the file upload size restriction at the server (tomcat) level?

It seems that spring.servlet.multipart.max-file-size is a better approach. This property is set for MultipartResolver bean automatically. This bean is created automatically in Springboot. In Spring and/or Spring MVC (basically, not Springboot), this bean needs to be created manually.
MultipartResolver bean is the one that handles the file size uploaded via a form. This approach is better because it doesn't load up the whole file. It gets the file size through a header, and if file size exceeds the value set as a value for the property spring.servlet.multipart.max-file-size, it throws an error.
Validating the file size via #Valid/Validator approach is not wise because the whole file will be uploaded to the server.

Related

spring boot: separate REST from static content

I'm using spring-boot-starter-data-rest and spring-boot-starter-web.
I've made a simple project using a CrudRepository, letting spring boot generate the rest request mappings.
Now, I want to add a client -- making the rest calls -- live under ./.
Hence, I'm trying to prefix the paths for the rest calls (and only those!) with /api.
I've tried the answers from :
How to specify prefix for all controllers in Spring Boot?
using settings in the application.properties file
server.contextPath=/api/*
spring.data.rest.basePath=/api/*.
But still the static content (e.g. index.html, *.js, *.css) is not fetched using ./. There urls are also prefixed by "/api/".
The rest calls are properly served under /api/foos.
Is there a way to tell spring not to treat urls that lead to sources located in src/main/resources/public as 'rest-controllers'?
Update
Setting the property
spring.data.rest.basePath=/api/*
works perfectly. (I still had a programmatic bean configuration in my sandbox overriding this setting).
Spring controllers are made for serving both HTML and JSON/XML. The first one is done via Spring MVC Views and some template engine like Thymeleaf, the latter is handled entirely by Spring and #RestController.
There's no way to have a context path for only the controllers that returns JSON or XML data, and not for the other controllers as well, this also goes for static content. What you typically do is have some static variable containing the prefix you want for your APIs, and the use that in the controller's #RequestMapping. i.e.
#RestController
#RequestMapping(MyConstants.API_LATEST + "/bookings")
public class MyBookingsController {
...
}
You probably want to approach the prefix problem with something along these lines anyway. It is common to have to support older API versions when you have breaking changes, at least for some time.

Spring StandardServletMultipartResolver

I was wondering where is located the code that automatically create a temporary file when you send a multipart request using StandardServletMultipartResolver?
Can i disable that behavior? I want to decide how its going to be stored and where. I don't want spring to do it for me.
I'm considering creating my own resolver but I cant find information on how to disable spring default behavior.
To quote from API docs StandardServletMultipartResolver does not support temporary file configuration on resolver level rather it is to be done on servlet registration level -
In order to use Servlet 3.0 based multipart parsing, you need to mark the affected servlet with a "multipart-config" section in web.xml, or with a MultipartConfigElement in programmatic servlet registration, or (in case of a custom servlet class) possibly with a MultipartConfig annotation on your servlet class.
Configuration settings such as maximum sizes or storage locations need to be applied at that servlet registration level; Servlet 3.0 does not allow for them to be set at the MultipartResolver level.
So either you can configure it on servlet or switch to CommonsMultipartResolver which has the support to set the temp directory out-of-the-box as it inherits it from CommonsFileUploadSupport.setUploadTempDir (see respective docs here and here)

Spring MVC: Customizing view response (Json/XML) based on header or parameter

I have a Spring MVC application which returns Json and Xml based on what is requested per client call. I am using Jackson and Xstream to let Spring do the de-serialization of my java object into json or xml output.
My java object contains a bunch of attributes, at least 30. I would like to know if there is a way I can let Spring control which fields of my java object will be present in the json or xml based on a header or parameter attribute. So the client application will be able to identify itself and the backend will return only the fields necessary or "visible" for that specific client app. Of course I could go to the nasty approach of hard coding, but I would not like to do that as the number of client applications can increase or decrease and having a deployment anytime it happens with code changes is out of context.
Is there a way to instruct spring/jackson/xstream to control the output based on some providaded value?
I did a quick implementation and my current solution works like this: I have an xml with a list of client IDs (I use these ids to identify my client app) and for each ID I have a list of attributes that the client app needs from the java object. I created a interceptor and between the controller and the view, my interceptor gets the header information with the client ID, get the list of attributes and using the BeanWrapper (http://docs.spring.io/spring/docs/2.0.x/reference/validation.html) to create a new object with only the attributes required by the client with data, all the others remain null (I instruct Jackson and Xtream) to ignore null attributes. This approach works fine but I was wondering if there is another/better way to do this.
Thank you
TL

Spring environment validation

We're building a Spring-based application which will be delivered to end users as a distribution package. Users are responsible for properly configuring whatever needs to be configured (it's mostly about various filesystem locations, folder access permissions, etc). There's a good idea to make the app help users understand what is not configured or which parts of configuration are invalid.
Our current approach is a custom ApplicationContextInitializer which does all the environment validation "manually" and then registers few "low level" beans in the application context explicitly. If something is wrong, initializer throws, exception is caught somewhere in main(), interpreted (converted into plain English) and then displayed.
While this approach works fine, I'm wondering if there are any best practices to minimize hand-written code and use Spring whenever possible.
Here's an illustrative example. The application requires a folder for file uploads. This means:
There should be a configuration file
This file should be accessible by the app
This file should have no syntax errors
This file should explicitly define some specific property (let it be app.uploads.folder)
This property should describe the existing filesystem entity
This entity should be a folder
The app should have read/write access to this folder
Does Spring provide any tools to implement this sort of validation easily?
Spring Boot has a nice feature for context and external configuration validation. If you define a POJO class and declare it as #ConfigurationProperties then Spring will bind the Environment (external properties and System/OS typically) to its properties using a DataBinder. E.g.
#ConfigurationProperties(name="app.uploads")
public class FileUploadProperties {
private File folder;
// getters and setters ommitted
}
will bind to app.uploads.folder and ensure that it is a File. For extra validation you can do it manually in the setter, or you can implement Validator in your FileUploadProperties or you can use JSR-303 annotations on the fields. By default an external property in app.uploads.* that doesn't bind will throw an exception (e.g. a mis-spelled property name, or a conversion/format error).
If you use Spring Boot Autoconfigure #EnableAutoConfigure you don't have to do anything else, but if it's just vanilla Spring (Boot) you need to say #EnableConfigurationProperties in your #Configuration somewhere as well.
A bonus feature: if you also use the Spring Boot Actuator you will also get JMX and HTTP support (in a webapp) for inspecting the bindable and bound properties of #ConfigurationProperties beans. The HTTP endpoint is "/configprops".

Spring - Adding element(checkbox) to Spring login page (with Spring-security)

In my web application I am using Spring login form (with Spring-security). By default the login form has the fields j_username and j_password. I need to add one more element(checkbox for Terms&Conditions). The current code doesn't have LoginForm as well as LoginController since Spring is internally handling it.
Can anyone please tell how to handle/override this?
I have seen this link Spring security custom login page
But I need to add the new element in LoginForm (which is not existing currently) - where I need to add this new element(in Form - .java file)
Also should I write a new controller (LoginController) or can I use any existing filter as given here? http://static.springsource.org/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#filter-stack
Does the user just have to check the box in order to procede, or does it bind to a backing model object.
If it's the former, I'd just handle it through javascript. If the latter, the easiest way would probably be implementing an Authentication Filter, this area of the documentation might help:
http://static.springsource.org/spring-security/site/docs/3.0.x/reference/core-web-filters.html#form-login-filter

Resources