Reputation: 2652
This request below is causing a 400 bad request response:
$scope.addGiveaway = function(campaignId){
var photo = $scope.photo;
var giveaway = $scope.giveaway;
var data = new FormData();
data.append('photo', photo);
data.append('giveaway', giveaway);
var uploadUrl = "/dashboard/campaigns/"+campaignId+"/giveaways";
$http.put(uploadUrl, data, {
transformRequest: angular.identity,
headers: {
'Content-Type': 'multipart/form-data',
}
});
Here's the Spring controller:
@RequestMapping(method = RequestMethod.PUT)
public ResponseEntity<String> addGiveaway(@RequestParam("giveaway") Giveaway giveaway,
@RequestParam("photo") MultipartFile photo,
@PathVariable("campaignId") long campaignId,
Principal principal) throws Exception {
I have a @RequestMapping
at the top of the entire controller class:
@RequestMapping("/dashboard/campaigns/{campaignId}/giveaways")
I've tried:
Giveaway
object to a String and using a mapper to map
the values manuallyangular.toJson
Content-Type
to undefined
and to
multipart/form-data
Why is this causing a 400 bad request response?
EDIT Posting entire controller class as requested. It shouldn't matter though as the logger at the top of the controller is not being called. It's not getting into the code of the controller.
@RestController
@RequestMapping("/dashboard/campaigns/{campaignId}/giveaways")
public class GiveawayController {
@Autowired
private GiveawayService giveawayService;
@Autowired
private CampaignService campaignService;
@Autowired
private BusinessUserService businessUserService;
private static final Logger logger = Logger.getLogger(GiveawayController.class);
/**
* Uploads a giveaway to the server given data and a photo.
*
* @param giveaway giveaway data to save
* @param photo photo of the giveaway item
* @param principal authenticated user
* @return status code and errors
* @throws Exception
*/
@RequestMapping(method = RequestMethod.PUT)
public ResponseEntity<String> addGiveaway(@RequestParam("giveaway") Giveaway giveaway,
@RequestParam("photo") MultipartFile photo,
@PathVariable("campaignId") long campaignId,
Principal principal) throws Exception {
logger.info("Made it into the controller");
Campaign campaign = campaignService.findOne(campaignId);
campaignService.verifyCampaignOwnership(
businessUserService
.findByEmail(principal.getName()), campaign);
//Validate form input
HttpHeaders headers = giveawayService.validateGiveawayData(giveaway);
//Validate image size & file type
String extension = FileUtils.resolveExtension(photo.getContentType());
if(FileUtils.isImage(extension)) {
if(FileUtils.checkDimensions(photo, GiveawayService.MIN_ALLOWED_SIZE,
GiveawayService.MAX_ALLOWED_SIZE, GiveawayService.MIN_ALLOWED_SIZE,
GiveawayService.MAX_ALLOWED_SIZE, true)) {
headers.add("Error-Giveaway-Image-Size", "Giveaway photo must be square and between 64-612 pixels.");
}
} else {
headers.add("Error-Giveaway-Image-Type", "Only .jpg and .png file types are allowed.");
}
//If headers are not empty, then there's either validation or input errors
if(!headers.isEmpty()) {
return new ResponseEntity<>(headers, HttpStatus.BAD_REQUEST);
} else {
giveaway.setPhotoExtension(extension);
giveaway.setStatus(GiveawayStatus.INACTIVE);
giveaway = giveawayService.save(giveaway);
FileUtils.uploadResource(photo, giveaway.getGiveawayId() + extension, GiveawayService.GIVEAWAY_STORING_LOCATION);
return new ResponseEntity<>(HttpStatus.CREATED);
}
}
}
Here's the giveaway POJO:
@Entity
@Table(name="GIVEAWAYS")
public class Giveaway implements Serializable {
private static final long serialVersionUID = -8835490774774467020L;
@Id
@Column(name="giveaway_id")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private long giveawayId;
@ManyToOne
@JoinColumn(name="campaign_id", foreignKey=@ForeignKey(name="give_campaign_id"), nullable=false)
private Campaign campaign;
@Column(name="giveaway_item")
private String giveawayItem;
@Column(name="description")
private String description;
@Column(name="photo_extension")
private String photoExtension;
@Column(name="amount_of_items")
private int amountOfItems;
@Column(name="status")
private String status;
@Column(name="eligibility")
private String eligibility;
//Getters and setters below...
And here's the JSON created from the form sent to the back end:
{giveawayItem: "testing", description: "test123", amountOfItems: 4, eligibility: "Followers"}
EDIT 3
Whenever I use angular.toJson
or JSON.stringify
on the data above, it turns it into this:
{"description":"dfgdg","amountOfItems":5,"eligibility":"Followers"}
For some reason, giveawayItem
disappears. I don't know if that's causing any issues, but it's certainly troubling.
EDIT 4
Debug logging
2016-10-31 13:40:35.097 DEBUG 2716 --- [nio-8090-exec-3] o.s.web.servlet.DispatcherServlet : DispatcherServlet with name 'dispatcherServlet' processing PUT request for [/dashboard/campaigns/1/giveaways]
2016-10-31 13:40:35.098 DEBUG 2716 --- [nio-8090-exec-3] s.w.s.m.m.a.RequestMappingHandlerMapping : Looking up handler method for path /dashboard/campaigns/1/giveaways
2016-10-31 13:40:35.102 DEBUG 2716 --- [nio-8090-exec-3] s.w.s.m.m.a.RequestMappingHandlerMapping : Returning handler method [public org.springframework.http.ResponseEntity<java.lang.String> com.glimpsmedia.app.controllers.GiveawayController.addGiveaway(com.glimpsmedia.app.model.Giveaway,org.springframework.web.multipart.MultipartFile,long,java.security.Principal) throws java.lang.Exception]
2016-10-31 13:40:35.121 DEBUG 2716 --- [nio-8090-exec-3] o.s.web.cors.DefaultCorsProcessor : Skip CORS processing: request is from same origin
2016-10-31 13:40:35.139 DEBUG 2716 --- [nio-8090-exec-3] .w.s.m.m.a.ServletInvocableHandlerMethod : Error resolving argument [0] [type=com.glimpsmedia.app.model.Giveaway]
HandlerMethod details:
Controller [com.glimpsmedia.app.controllers.GiveawayController]
Method [public org.springframework.http.ResponseEntity<java.lang.String> com.glimpsmedia.app.controllers.GiveawayController.addGiveaway(com.glimpsmedia.app.model.Giveaway,org.springframework.web.multipart.MultipartFile,long,java.security.Principal) throws java.lang.Exception]
org.springframework.web.bind.MissingServletRequestParameterException: Required Giveaway parameter 'giveaway' is not present
at org.springframework.web.method.annotation.RequestParamMethodArgumentResolver.handleMissingValue(RequestParamMethodArgumentResolver.java:195) ~[spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:104) ~[spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121) ~[spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:161) [spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:128) [spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:114) [spring-webmvc-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) [spring-webmvc-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) [spring-webmvc-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) [spring-webmvc-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963) [spring-webmvc-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897) [spring-webmvc-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) [spring-webmvc-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doPut(FrameworkServlet.java:883) [spring-webmvc-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:651) [tomcat-embed-core-8.5.4.jar:8.5.4]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) [spring-webmvc-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) [tomcat-embed-core-8.5.4.jar:8.5.4]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230) [tomcat-embed-core-8.5.4.jar:8.5.4]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) [tomcat-embed-core-8.5.4.jar:8.5.4]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) [tomcat-embed-websocket-8.5.4.jar:8.5.4]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) [tomcat-embed-core-8.5.4.jar:8.5.4]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) [tomcat-embed-core-8.5.4.jar:8.5.4]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:317) [spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127) [spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91) [spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:115) [spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137) [spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) [spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:169) [spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) [spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilterInternal(BasicAuthenticationFilter.java:158) [spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200) [spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at com.glimpsmedia.app.security.StatelessAuthenticationFilter.doFilter(StatelessAuthenticationFilter.java:52) [classes/:na]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200) [spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:121) [spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at com.glimpsmedia.app.security.CsrfTokenFilter.doFilterInternal(CsrfTokenFilter.java:46) [classes/:na]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:124) [spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:66) [spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) [spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) [spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214) [spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177) [spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346) [spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262) [spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) [tomcat-embed-core-8.5.4.jar:8.5.4]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) [tomcat-embed-core-8.5.4.jar:8.5.4]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) [spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) [tomcat-embed-core-8.5.4.jar:8.5.4]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) [tomcat-embed-core-8.5.4.jar:8.5.4]
at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:87) [spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) [tomcat-embed-core-8.5.4.jar:8.5.4]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) [tomcat-embed-core-8.5.4.jar:8.5.4]
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77) [spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) [tomcat-embed-core-8.5.4.jar:8.5.4]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) [tomcat-embed-core-8.5.4.jar:8.5.4]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) [spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) [tomcat-embed-core-8.5.4.jar:8.5.4]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) [tomcat-embed-core-8.5.4.jar:8.5.4]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) [tomcat-embed-core-8.5.4.jar:8.5.4]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:108) [tomcat-embed-core-8.5.4.jar:8.5.4]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:522) [tomcat-embed-core-8.5.4.jar:8.5.4]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.4.jar:8.5.4]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) [tomcat-embed-core-8.5.4.jar:8.5.4]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.4.jar:8.5.4]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349) [tomcat-embed-core-8.5.4.jar:8.5.4]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:1110) [tomcat-embed-core-8.5.4.jar:8.5.4]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.4.jar:8.5.4]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:785) [tomcat-embed-core-8.5.4.jar:8.5.4]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1425) [tomcat-embed-core-8.5.4.jar:8.5.4]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.4.jar:8.5.4]
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [na:1.8.0_91]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [na:1.8.0_91]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.4.jar:8.5.4]
at java.lang.Thread.run(Unknown Source) [na:1.8.0_91]
2016-10-31 13:40:35.140 DEBUG 2716 --- [nio-8090-exec-3] .m.m.a.ExceptionHandlerExceptionResolver : Resolving exception from handler [public org.springframework.http.ResponseEntity<java.lang.String> com.glimpsmedia.app.controllers.GiveawayController.addGiveaway(com.glimpsmedia.app.model.Giveaway,org.springframework.web.multipart.MultipartFile,long,java.security.Principal) throws java.lang.Exception]: org.springframework.web.bind.MissingServletRequestParameterException: Required Giveaway parameter 'giveaway' is not present
2016-10-31 13:40:35.140 DEBUG 2716 --- [nio-8090-exec-3] .w.s.m.a.ResponseStatusExceptionResolver : Resolving exception from handler [public org.springframework.http.ResponseEntity<java.lang.String> com.glimpsmedia.app.controllers.GiveawayController.addGiveaway(com.glimpsmedia.app.model.Giveaway,org.springframework.web.multipart.MultipartFile,long,java.security.Principal) throws java.lang.Exception]: org.springframework.web.bind.MissingServletRequestParameterException: Required Giveaway parameter 'giveaway' is not present
2016-10-31 13:40:35.140 DEBUG 2716 --- [nio-8090-exec-3] .w.s.m.s.DefaultHandlerExceptionResolver : Resolving exception from handler [public org.springframework.http.ResponseEntity<java.lang.String> com.glimpsmedia.app.controllers.GiveawayController.addGiveaway(com.glimpsmedia.app.model.Giveaway,org.springframework.web.multipart.MultipartFile,long,java.security.Principal) throws java.lang.Exception]: org.springframework.web.bind.MissingServletRequestParameterException: Required Giveaway parameter 'giveaway' is not present
2016-10-31 13:40:35.141 DEBUG 2716 --- [nio-8090-exec-3] o.s.web.servlet.DispatcherServlet : Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling
2016-10-31 13:40:35.141 DEBUG 2716 --- [nio-8090-exec-3] o.s.web.servlet.DispatcherServlet : Successfully completed request
2016-10-31 13:40:35.142 DEBUG 2716 --- [nio-8090-exec-3] o.s.web.servlet.DispatcherServlet : DispatcherServlet with name 'dispatcherServlet' processing PUT request for [/error]
2016-10-31 13:40:35.142 DEBUG 2716 --- [nio-8090-exec-3] s.w.s.m.m.a.RequestMappingHandlerMapping : Looking up handler method for path /error
2016-10-31 13:40:35.144 DEBUG 2716 --- [nio-8090-exec-3] s.w.s.m.m.a.RequestMappingHandlerMapping : Returning handler method [public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)]
2016-10-31 13:40:35.144 DEBUG 2716 --- [nio-8090-exec-3] o.s.web.cors.DefaultCorsProcessor : Skip CORS processing: request is from same origin
2016-10-31 13:40:35.149 DEBUG 2716 --- [nio-8090-exec-3] o.s.w.s.m.m.a.HttpEntityMethodProcessor : Written [{timestamp=Mon Oct 31 13:40:35 EDT 2016, status=400, error=Bad Request, exception=org.springframework.web.bind.MissingServletRequestParameterException, message=Required Giveaway parameter 'giveaway' is not present, path=/dashboard/campaigns/1/giveaways}] as "application/json" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@7cbe3a05]
2016-10-31 13:40:35.149 DEBUG 2716 --- [nio-8090-exec-3] o.s.web.servlet.DispatcherServlet : Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling
2016-10-31 13:40:35.149 DEBUG 2716 --- [nio-8090-exec-3] o.s.web.servlet.DispatcherServlet : Successfully completed request
Upvotes: 2
Views: 1974
Reputation: 3109
Here's my interpretation of your problem.
Actually you're struggling to transmit the object from the Angular front side and trying to get it through @RequestParam which is naturally can't be straightforward as @RequestParam will normally works on string type, means it can't just map a complex object . It's all makes sense as the 400 http code is indicating a malformed request.
A possible solution (notice that @RequestBody
instead of @RequestParam
on Giveaway ):
// Angular side
$scope.addGiveaway = function(campaignId){
var photo = $scope.photo;
var giveaway = $scope.giveaway;
var data = new FormData();
data.append('photo', photo);
data.append('giveaway', giveaway);
var uploadUrl = "/dashboard/campaigns/"+campaignId+"/giveaways";
$http.put(uploadUrl, data, {
transformRequest: angular.identity,
headers: {
'Content-Type': 'multipart/form-data',
}
});
// Spring side
@RequestMapping(method = RequestMethod.PUT)
public ResponseEntity<String> addGiveaway(@RequestBody Giveaway giveaway,
@RequestParam("photo") MultipartFile photo,
@PathVariable("campaignId") long campaignId,
Principal principal) throws Exception {
Upvotes: 0
Reputation: 2652
I fixed it. I changed the Giveaway
object to a String and parsed that with an ObjectMapper
. Here's my new controller:
@RequestMapping(method = RequestMethod.PUT)
public ResponseEntity<String> addGiveaway(@RequestParam("giveaway") String giveawayData,
@RequestParam("photo") MultipartFile photo,
@PathVariable("campaignId") long campaignId,
Principal principal) throws Exception {
I then used var giveaway = angular.toJson($scope.giveaway)
to format the json properly. I then appended the giveaway data to the end of the request instead of adding it to the form data, like this:
'.../giveaways?giveaway=' + giveaway;
Upvotes: 0
Reputation: 22462
Your request url /dashboard/campaigns/"+campaignId+"/giveaways is not actually mapped to the controller
method.
As you need to pass campaignId
as @PathVariable
, you should map it, in your controller method.
Class Level Mapping (at top): /dashboard/campaigns/
Method Level Mapping : {campaignId}/giveaways
The code follows below:
@RestController(value = "/dashboard/campaigns/") {
public class GiveawayController {
@RequestMapping(value="{campaignId}/giveaways", method =RequestMethod.PUT)
public ResponseEntity<String> addGiveaway(
@RequestParam("giveaway")Giveaway giveaway,
@RequestParam("photo") MultipartFile photo,
@PathVariable("campaignId") long campaignId,
Principal principal) throws Exception {
//code here
}
}
P.S.: I have assumed that /dashboard/campaigns/
mapping at class level.
Upvotes: 1