I have a simple method where I need to change the contentType to "text/plain" but when I am using Jboss EAP 6.2 it is ignored and the returned value is "application/json.
#RestController
#RequestMapping("/upload")
public class UploadController {
...
#RequestMapping(method = RequestMethod.POST)
public Result foo(MultipartFile arquivo, HttpServletResponse response) {
response.setContentType("text/plain");
return uploadService.saveFile(arquivo);
}
}
I am using SpringMVC (rest controller) and Jackson to parse to JSON. The exactly same method works fine when I use Jetty instead of Jboss.
I can't use #RequestMapping(produces="text/plain") because the actual method has a bit more logic into it and sometimes it will return application/json others text/plain, depending if the request came from IE9 browser or not.
Can someone please tell me how can I set the contentType on Jboss?
Unfortunately the only way I could get this working for Jboss was creating a different method for IE9:
#RequestMapping(value = "/ie9", method = RequestMethod.POST, produces = MediaType.TEXT_PLAIN_VALUE)
public String fooIE9(#RequestParam("arquivo") MultipartFile arquivo) throws JsonProcessingException {
ObjectWriter ow = new ObjectMapper().writer();
return ow.writeValueAsString(uploadService.saveFile(arquivo));
}
Related
Is there a way to add Gzip for one method or controller in spring
#RequestMapping(value = "/system", method = {RequestMethod.GET})
#Gzip //<- Something similar this,
public ApiResponse status() throws Exception{
}
I dont want to enable it for the entire server using tomcat configuration, since my clients are not yet ready for consuming gzip,
You can put java.io.OutputStream or javax.servlet.http.HttpServletResponse (for specific gzip HTTP headers) to your Controller method as parameter wrapping it with java.util.zip.GZIPOutputStream before writing the content to the client
#RequestMapping(value = "/system", method = {RequestMethod.GET})
public void status(HttpServletResponse response) throws Exception {
try(GZIPOutputStream out = new GZIPOutputStream(response.getOutputStream())) {
// write to out the content
}
}
I´m using swagger on my java EE7 application (Glassfish as application server). Everything works fine except for a method with FormDataParam, which gave me the tradicional error:
org.glassfish.jersey.server.ContainerException: java.lang.NoSuchMethodError: com.fasterxml.jackson.databind.AnnotationIntrospector.findPropertyIndex(Lcom/fasterxml/jackson/databind/introspect/Annotated;)Ljava/lang/Integer;
I tried everything, but is just a method, so I do not want so badly this method in my swagger.json
How can I exclude this method from swagger. I tried:
#ApiModelProperty(hidden = true) and #ApiOperation(value="",hidden = true)
#POST
#Path("something")
#Produces(MediaType.TEXT_PLAIN)
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response newsomething(#FormParam("something") String something,#Context HttpServletRequest request, #Context HttpServletResponse response) throws IOException {
return "something";
}
What I´m doing wrong?
It's related with Glassfish, it use different version of Jackson. You need to upgrade Glassfish/Jackson. More details:
java.lang.NoSuchMethodError: com.fasterxml.jackson.databind.AnnotationIntrospector.findPropertyIndex(Lcom/fasterxml/jackson/databind/introspect/Annotated;)Ljava/lang/Integer solution https://github.com/swagger-api/swagger-core/issues/1001
Upgrading Jackson in GlassFish 4.1
com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector not found --- while using Swagger
java.lang.NoSuchMethodError: com.fasterxml.jackson.databind.AnnotationIntrospector.findPropertyIndex(Lcom/fasterxml/jackson/databind/introspect/Annotated;)Ljava/lang/Integer; solution - https://groups.google.com/forum/#!topic/swagger-swaggersocket/uQEn-anX_Og
java.lang.NoSuchMethodError: com.fasterxml.jackson.databind.AnnotationIntrospector.findPropertyDesc solution https://groups.google.com/forum/#!topic/swagger-swaggersocket/x-Pz_3orTCE
For me adding #ApiModelProperty(hidden = true) in paths worked
Is it wrong or correct?
#ApiModelProperty(hidden = true)
#GET
#Produces({MediaType.APPLICATION_JSON})
#ApiOperation(value = "return getApi ",
tags = {"getApi"},
notes = "Returns a Array of getApi",
hidden = true
)
#ApiResponses(value = {
#ApiResponse(response = GetApi.class, message = "", code = 200)
})
#Path("getApi")
public Response getApi(#Context HttpHeaders httpHeaders, #BeanParam QueryParamBean queryParamBean) {
// codes..
}
I'm updating my application from
spring 3.2.5 to 4.2.0
spring security 3.1.4 to 4.0.2.
A lot of my controllers which used to display HTML now display plain text.
I created a few test methods, the following displayed HTML in version 3 and displays plain text in version 4:
#RequestMapping(value = "/htmltest", method = RequestMethod.GET)
public void test(Writer writer, HttpServletRequest request, HttpServletResponse response) throws IOException {
writer.append("<html><head></head><body>"); //$NON-NLS-1$
writer.append("this is a HTML test");
writer.append("</body></html>"); //$NON-NLS-1$
writer.flush();
}
I also added produces = "text/html" to the #RequestMapping, did not have an effect.
I think this only has an effect using #ResponseBody? Did the following test:
#ResponseBody
#RequestMapping(value = "/htmltest2", method = RequestMethod.GET, produces = "text/html")
public String test2(HttpServletRequest request, HttpServletResponse response) {
StringBuilder str = new StringBuilder();
str.append("<html><head></head><body>"); //$NON-NLS-1$
str.append("this is a HTML test");
str.append("</body></html>"); //$NON-NLS-1$
return str.toString();
}
This displays HTML and if I switch to produces = "text/plain" returns text.
So the question is how do I get controllers to produce HTML where the writer is being used?
I found out that I can set the content type on the response response.setContentType("text/html"), but would prefer not having to do that for all my controllers.
Especially since it worked in the previous spring version, could it be a configuration problem?
#RequestMapping(value = "/htmltest3", method = RequestMethod.GET)
public void test3(Writer writer, HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setContentType("text/html");
writer.append("<html><head></head><body>"); //$NON-NLS-1$
writer.append("this is a HTML test");
writer.append("</body></html>"); //$NON-NLS-1$
writer.flush();
}
Edit: I just found out that only Chrome (44.0.2403.155 m) does not display HTML, Firefox (40.0.2) and InternetExplorer (11.0.9600.17959) work as expected.
Still it may also not work in older browser versions, but maybe this gives a hint?
So the problem was the headers which have been introduced in Spring Security 3.2.0:
http://spring.io/blog/2013/08/23/spring-security-3-2-0-rc1-highlights-security-headers/
If I add the following lines to my application context, the controllers display HTML again.
<http>
...
<headers disabled="true"/>
</http>
Well but this is a bad idea since it will disable all the additional seurity features (X-XSS-Protection, X-Frame-Options, HSTS).
So one option could be to disable the defaults and configure own headers:
<http>
...
<headers defaults-disabled="true">
<frame-options policy="SAMEORIGIN" />
</headers>
</http>
After narrowing it down this solves my issue:
<http>
...
<headers>
<content-type-options disabled="true" />
</headers>
</http>
There are some security aspects that need to be considered, but for me this works for now.
http://docs.spring.io/autorepo/docs/spring-security/4.0.x/reference/html/headers.html#headers-content-type-options
Try:
#ResponseBody
#RequestMapping(value = "/htmltest3", method = RequestMethod.GET)
public void test3(Writer writer, HttpServletRequest request, HttpServletResponse response) throws IOException {
String html = "<html><head></head><body>this is a HTML test</body></html>";
return html;
}
I try to have a redirect with 301 Status Code (you know I want to be SEO friendly etc).
I do use InternalResourceViewResolver so I wanted to use some kind of a code similar to return "redirect:http://google.com" in my Controller.
This though would send a 302 Status Code
What I have tried is using a HttpServletResponse to set header
#RequestMapping(value="/url/{seo}", method = RequestMethod.GET)
public String detail(#PathVariable String seo, HttpServletResponse response){
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return "redirect:http://google.com";
}
It does still return 302.
After checking documentation and Google results I've come up with the following:
#RequestMapping(value="/url/{seo}", method = RequestMethod.GET)
public ModelAndView detail(#PathVariable String seo){
RedirectView rv = new RedirectView();
rv.setStatusCode(HttpStatus.MOVED_PERMANENTLY);
rv.setUrl("http://google.com");
ModelAndView mv = new ModelAndView(rv);
return mv;
}
It does work perfectly fine and as expected, returning code 301
I would like to achieve it without using ModelAndView (Maybe it's perfectly fine though). Is it possible?
NOTE: included snippets are just parts of the detail controller and redirect does happen only in some cases (supporting legacy urls).
I would suggest using redirectView of spring like you have it. You have to have a complete URL including the domain etc for that to work, else it will do a 302. Or if you have access to HttpServletResponse, then you can do the below as below.
public void send301Redirect(HttpServletResponse response, String newUrl) {
response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
response.setHeader("Location", newUrl);
response.setHeader("Connection", "close");
}
Not sure when it was added, but at least on v4.3.7 this works. You set an attribute on the REQUEST and the spring View code picks it up:
#RequestMapping(value="/url/{seo}", method = RequestMethod.GET)
public String detail(#PathVariable String seo, HttpServletRequest request){
request.setAttribute(View.RESPONSE_STATUS_ATTRIBUTE, HttpStatus.MOVED_PERMANENTLY);
return "redirect:http://google.com";
}
If you already return a ModelAndView and don't want to use HttpServletResponse, you can use this snippet:
RedirectView rv = new RedirectView("redirect:" + myNewURI);
rv.setStatusCode(HttpStatus.MOVED_PERMANENTLY);
return new ModelAndView(rv);
I am converting Java web application to Spring framework and appreciate some advice on the issues I am facing with the file upload. Original code was written using org.apache.commons.fileupload.
Does Spring MultipartFile wraps org.apache.commons.fileupload or I can exclude this dependency from my POM file?
I have seen following example:
#RequestMapping(value = "/form", method = RequestMethod.POST)
public String handleFormUpload(#RequestParam("file") MultipartFile file) {
if (!file.isEmpty()) {
byte[] bytes = file.getBytes();
// store the bytes somewhere
return "redirect:uploadSuccess";
} else {
return "redirect:uploadFailure";
}
}
Originally I tried to follow this example but was always getting an error as it couldn't find this request param. So, in my controller I have done the following:
#RequestMapping(value = "/upload", method = RequestMethod.POST)
public #ResponseBody
ExtResponse upload(HttpServletRequest request, HttpServletResponse response)
{
// Create a JSON response object.
ExtResponse extResponse = new ExtResponse();
try {
if (request instanceof MultipartHttpServletRequest)
{
MultipartHttpServletRequest multipartRequest =
(MultipartHttpServletRequest) request;
MultipartFile file = multipartRequest.getFiles("file");
InputStream input = file.getInputStream();
// do the input processing
extResponse.setSuccess(true);
}
} catch (Exception e) {
extResponse.setSuccess(false);
extResponse.setMessage(e.getMessage());
}
return extResponse;
}
and it is working. If someone can tell me why #RequestParam did not work for me, I will appreciate. BTW I do have
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="2097152"/>
</bean>
in my servlet context file.
I had to
add commons-fileupload dependency to my pom,
add multipartResolver bean (mentioned in the question),
use #RequestParam("file") MultipartFile file in the handleFormUpload method and
add enctype in my jsp : <form:form method="POST" action="/form" enctype="multipart/form-data" >
to get it to work.
spring does not have a dependency on commons-fileupload, so you'll need it. If it's not there spring will use its internal mechanism
You should pass a MultipartFile as a method parameter, rather than #RequestParam(..)
This works for me.
#RequestMapping(value = "upload.spr", method = RequestMethod.POST)
public ModelAndView upload(#RequestParam("file") MultipartFile file, HttpServletResponse response)
{
// handle file here
}
The General sysntax for request param is this #RequestParam(value="Your value", required=true),
mode over request param is used to get a value frm the Url.
In a POST you will only send the params in the request body, not in the URL (for which you use #RequestParams)
Thats why your second method worked.
In Spring MVC 3.2 support for Servet 3.0 was introduced. So you need to include commons-file upload if you use earlier versions of Spring.