I have configured the access decision manager to check a request before being processed by the servlet the key line is:-
HttpServletRequest request = (HttpServletRequest) RequestContextHolder.currentRequestAttributes().getRequest();
All good. However when the request is enctype="multipart/form-data" how do I get hold of the MultipartHttpServletRequest when RequestContextHolder.currentRequestAttributes().getRequest() only returns HttpServletRequest?
I am using spring 2.5.
MultipartHttpServletRequest is n Spring-specific interface for handling multipart form submissions. The default implementation is DefaultMultipartHttpServletRequest, which has a constructor that takes a HttpServletRequest.
So:
HttpServletRequest originalRequest = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
MultipartHttpServletRequest multiPartRequest = new DefaultMultipartHttpServletRequest(originalRequest);
Apart from having
<form method=<method> action=<url> enctype="multipart/form-data"></form>
you have to have
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />
in your spring configuration file.
Here is nice tutorial on the same
http://techdive.in/spring/spring-file-upload
Have you tried casting to MultipartHttpServletRequest?
If you are using spring-mvc, make sure you put this line
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />
in your app-config.xml.
This worked for me.
I don't think you can get DefaultMultipartHttpServletRequest from RequestContextHolder.
DefaultMultipartHttpServletRequest really implements HttpServletRequest.
But there're 2 request instances if you use CommonsMultipartResolver. One is DefaultMultipartHttpServletRequest instance, and another is HttpServletRequest instance.
Actually I don't know how to get the first instance from RequestContextHolder. You can get the second instance from it.
Related
In my controller when sending parameter as form-data, its receiving as null value.
When passing parameter as x-www-form-urlencoded, I am getting the value.
My controller is like the following:
#RequestMapping(value = "/getid", method = RequestMethod.POST)
public ServerResponse id(#RequestParam(value = "id", required = false) String id) {...}
If you need to send parameters are form-data then you need to add support for this in Spring,
Have a look at spring's documentation http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-multipart
Spring’s built-in multipart support handles file uploads in web
applications. You enable this multipart support with pluggable
MultipartResolver objects, defined in the
org.springframework.web.multipart package. Spring provides one
MultipartResolver implementation for use with Commons FileUpload and
another for use with Servlet 3.0 multipart request parsing.
By default, Spring does no multipart handling, because some developers
want to handle multiparts themselves. You enable Spring multipart
handling by adding a multipart resolver to the web application’s
context. Each request is inspected to see if it contains a multipart.
If no multipart is found, the request continues as expected. If a
multipart is found in the request, the MultipartResolver that has been
declared in your context is used. After that, the multipart attribute
in your request is treated like any other attribute.
This is an example of how to use CommonsMultipartResolver
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- one of the properties available; the maximum file size in bytes -->
<property name="maxUploadSize" value="100000"/>
</bean>
Of course you also need to put the appropriate jars in your classpath
for the multipart resolver to work. In the case of the
CommonsMultipartResolver, you need to use commons-fileupload.jar.
I am trying to merge two Spring based projects into one but I am having an issue with MultiPartResolver. Inside my merged application there are two classes that use uploaded POST methods using different upload methods.
One uses the HttpServletRequest to retrieve the uploaded file :
#RequestMapping(method = RequestMethod.POST)
public #ResponseBody void handleResult(HttpServletRequest request,
HttpServletResponse response)
and the other uses MultipartFile to get the file and another field called notes which is passed to the form:
#RequestMapping(method = RequestMethod.POST)
public #ResponseBody String handleFormUpload(#RequestParam("notes")
String notes, #RequestParam("file") MultipartFile file)
The code then references 'file' to process the uploaded file.
The problem I have is the MultipartFile class requires this in the applicationContext.xml:
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="250000000"/>
</bean>
When this is in the applicationContext.xml file the original Servlet based method of posting fails. The POST request reaches this class but the file seems to have been stripped out as it processes it. As soon as I comment this out of the applicationContext.xml, the servlet method works again. However, the section of the code that uses the MultipartResolver now fails!
I do not have much experience of Spring but I'm trying my best to do this. I cannot work out how to prevent CommonsMultipartResolver from manipulating the POST files that are destined for the Servlet based class.
Can anybody help me?
I'm implementing a SOAP client that interacts with some legacy SOAP services.
All of SOAP body requests have the same format, like this:
<soap:Body>
<execute>
<msg>
</msg>
</execute>
</soap:Body>
As content, the msg element supports a list of any XML tags, so I can send any type of element inside msg: orders, customer, contacts, etc..
All of the requests also have the same action name.
Due to the restrictions/aspects above, if I use spring's PayloadRootAnnotationMethodEndpointMapping, since the root element in the soap body is the same for all the requests, each request will fall in the same method of my Endpoint. If I use spring's SoapActionAnnotationMethodEndpointMapping, since the action is the same for every requests, all of them will fall in the same method again.
The only thing I've got different in the requests, is the requesting URI.
It changes by the name of the operation that I'm invoking. Like:
http://host:port/services/Operation1?Wsdl or
http://host:port/services/Operation2?Wsdl
My idea was to have an endpoint for each type of requests. For example: all request related to products would fit into a "ProductsEndpoint".
I wanted to create a custom endpoint mapping that would extend springs AbstractEndpointMapping. In my implementation I would decide which endpoint to call based on the URI.
But how can I register my custom endpoint mapping in the spring's endpoint mapping chain?
Best regards
If anyone has a request like mine explained above, here goes what I've decided to do...
I've create a class MultipleMarshallersPayloadMethodProcessor extending spring org.springframework.ws.server.endpoint.adapter.method.MarshallingPayloadMethodProcessor. This is the class responsible for marshalling and unmarshalling arguments. In this class I've defined a java.util.map that will associate a given URL to a specific Marshaller. If the current URL request isn't a key in the map, it would use the default Marshaller supplied by the MarshallingPayloadMethodProcessor class.
To register the class as a spring bean:
<bean id="marshallingPayloadMethodProcessor"
class="br.com.tim.fiber.middleware.services.server.helpers.MultipleMarshallersPayloadMethodProcessor">
<constructor-arg ref="defaultMarshaller" />
<property name="otherMarshallers">
<map>
<entry key="/Operation1?wsdl" value-ref="operation1Marshaller"></entry>
<entry key="/Operation2?wsdl" value-ref="operation2Marshaller"></entry>
</map>
</property>
</bean>
And an example of a marshaller:
<bean id="operation1Marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="contextPaths">
<list>
<value>com.app.dtos.operation1</value>
<value>com.app.dtos.common</value>
</list>
</property>
</bean>
With this setup I was able to marshall and unmarshall any request according to the URL. Then I've used the Facade design pattern to create a SOAP Endpoint with a single method that receives all the requests. That method just inspects the URL and delegates to specific endpoints.
#Endpoint
public class FacadeEndpoint {
private static final String NAMESPACE_URI = "http://my.namespace.com/services";
#Autowired
private RequesEndpointURLExtractor requestUrlExtractor;
#Autowired
private OrdersEndpoint ordersEndpoint;
#SuppressWarnings("unchecked")
#PayloadRoot(namespace = NAMESPACE_URI, localPart = "execute")
#ResponsePayload
public ExecuteResponse dispatch(#RequestPayload Execute request) {
String serviceURL = this.requestUrlExtractor.getCurrentURL();
ExecuteResponse response = null;
if (serviceURL.equals(ServiceRequestsEndpoint.CREATE_ENDPOINT_URI)) {
Operation1DTO serviceRequest = (Operation1DTO) request.getMsg().getAnies().get(0);
}
...
}
The RequestEnpointURLExtractor is just a spring bean that extracts the full URL from the request.
#Component
public class RequesEndpointURLExtractor {
public String getCurrentURL() {
TransportContext ctx = TransportContextHolder.getTransportContext();
HttpServletRequest httpServletRequest = ((HttpServletConnection) ctx.getConnection()).getHttpServletRequest();
String pathInfo = httpServletRequest.getPathInfo();
String queryString = httpServletRequest.getQueryString();
return pathInfo + "?" + queryString;
}
}
I could create a custom annotation that would have a URL associated, and use that annotation on methods that would process the request with the URL configured. That would be a cleaner solution instead of the if/else if ladder that I have.
But, since this was only for a simple mockup server, the if/else if ladder isn't such a big deal.
I use Jersey create a sample API.
When client request this API, it will redirect client to anthoer URI.
The following is my code:
reidrectURI = URI.create(originalAlfDownloadLink);
return Response.seeOther(reidrectURI).build();
I want to add some customs http header into redirect uri.
Is it possible?
Yes you can do that, You can get hold of the httpRequest object and can add the desired headers before redirecting it. You can use the #Context annotation to get hold of the httpRequest.
#Context HttpServletRequest httpRequest
Once you have the httpRequest object then you can add headers to it like this:
httpRequest.getSession().setAttribute("header", "value");
An XML file is being posted to a url that my spring mvc is responding to.
In .NET, I could do this:
request.Form[0]
request.Form["abc"]
or
request.QueryString[0]
request.QueryString["some_key"]
Now with spring/servlets it seems I can only do this:
request.getParameter("some_key")
or get all the names or values.
When someone is posting a file to a url, using http post, won't this be just a single request parameter then?
Can I get the parameter using index with servlets?
When someone is posting a file to a url, using http post, won't this be just a single request parameter then?
Not necessarily. If the form contains more fields, then we'd have more parameters.
Can I get the parameter using index with servlets?
AFAIK, No. request.getParameter() doesn't return an array or a collection. So can't do that with request.getParameter()
request.getParameterValues(String) returns an array - but only the values associated with the given parameter name
request.getParameterMap() works on keys, and not ordered. That won't help either.
If you are using annotation based Spring controllers then this should work :
#RequestMapping(value="/upload.view")
public ModelAndView upload(HttpServletRequest request, HttpServletResponse response, #RequestParam("file") MultipartFile f) {
if (f == null) {
return new ModelAndView("upload", "msg", "The file is null.");
}
return new ModelAndView("upload", "msg", "File ( " + f.getOriginalFilename() + ") successfully uploaded.");
}
Additionally you need to add this to your application context
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.C ommonsMultipartResolver">
<!-- Max size in bytes. -->
<property name="maxUploadSize" value="100000"/>
</bean>
if you are using the old style controllers then you can do what is suggested in the Spring documentation (but it is more complex) http://static.springsource.org/spring/docs/3.0.0.M3/spring-framework-reference/html/ch16s08.html