Hello and thank you in advanced:
I'm using Spring 4 and jquery trying to PUT data to a RestController. I have three values that are passed to the controller: id, name, genre. For some reason, the PUT request works every time that I change the name field, but if I try to update just the genre field, the request never even hits the controller and fails with 400: Bad Request.
I'm totally stumped. My GET, POST, and DELETE methods are working just fine too. I'm going to include my config stuff since there's a good possibility that may be the issue...
manage-artist.js (knockout and jquery):
...
//update artist
self.updateArtist = function(artist){
self.clearMessages();
//put to database
$.ajax({
url: "../artist/" + artist.id(),
method: "PUT",
data: "id="+artist.id()+"&name="+artist.name()+"&genre="+artist.genre(),
datatype: "json",
success: function (data) {
console.log("Artist succesfully updated.");
//update message
self.successMessage("Artist successfully updated.");
},
error: function (err) {
console.log("An error occured while trying to update artist.");
//extract json response
self.errorResponse(err.responseJSON);
//...more error handling
}
});
};
...
ArtistController.java:
@RestController
@RequestMapping(value="/artist")
public class ArtistController {
@Autowired
private ArtistService artistService;
@Autowired
private ArtistValidator artistValidator;
@InitBinder
private void initBinder(WebDataBinder binder) {
binder.setValidator(artistValidator);
}
@RequestMapping(value="/", method=RequestMethod.GET)
public List<Artist> newArtistPage() {
return artistService.findAll();
}
@RequestMapping(value="/{id}", method=RequestMethod.GET)
public Artist artistListPage(@PathVariable Integer id) {
return artistService.findById(id);
}
@RequestMapping(value="/", method=RequestMethod.POST)
public Artist createArtist(@ModelAttribute @Valid Artist artist,
BindingResult result) {
//If there's validation errors
if (result.hasErrors())
throw new InvalidRequestException("Error creating artist", result);
return artistService.create(artist);
}
@RequestMapping(value="/{id}", method=RequestMethod.PUT)
public Artist editArtist(@ModelAttribute @Valid Artist artist, @PathVariable Integer id,
BindingResult result) {
//If there's validation errors
if (result.hasErrors())
throw new InvalidRequestException("Error updating artist", result);
//call update service
Artist updatedArtist;
try {
updatedArtist = artistService.update(artist);
} catch (ArtistNotFoundException e) {
throw new ResourceNotFoundException("Unable to update artist with ID = "+ id
+". No such artist exists.");
}
return updatedArtist;
}
@RequestMapping(value="/{id}", method=RequestMethod.DELETE)
public Artist deleteArtist(@PathVariable Integer id)
{
//call delete service
Artist deletedArtist;
try {
deletedArtist = artistService.delete(id);
} catch (ArtistNotFoundException e) {
throw new ResourceNotFoundException("Unable to delete artist with ID = "+ id
+". No such artist exists.");
}
return deletedArtist;
}
}
Initializer.java:
public class Initializer implements WebApplicationInitializer {
private static final String DISPATCHER_SERVLET_NAME = "dispatcher";
public void onStartup(ServletContext servletContext)
throws ServletException {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(WebAppConfig.class);
servletContext.addListener(new ContextLoaderListener(ctx));
ctx.setServletContext(servletContext);
Dynamic servlet = servletContext.addServlet(DISPATCHER_SERVLET_NAME,
new DispatcherServlet(ctx));
servlet.addMapping("/");
servlet.setLoadOnStartup(1);
}
}
WebAppConfig.java:
@Configuration
@EnableWebMvc
@EnableTransactionManagement
@ComponentScan("com.project.jukebox")
@PropertySource("classpath:jdbc.properties")
@EnableJpaRepositories("com.project.jukebox.repositories")
public class WebAppConfig extends WebMvcConfigurerAdapter {
private static final String PROPERTY_NAME_DATABASE_DRIVER = "jdbc.driver";
private static final String PROPERTY_NAME_DATABASE_PASSWORD = "jdbc.password";
private static final String PROPERTY_NAME_DATABASE_URL = "jdbc.url";
private static final String PROPERTY_NAME_DATABASE_USERNAME = "jdbc.username";
private static final String PROPERTY_NAME_HIBERNATE_DIALECT = "hibernate.dialect";
private static final String PROPERTY_NAME_HIBERNATE_SHOW_SQL = "hibernate.show_sql";
private static final String PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN = "entitymanager.packages.to.scan";
@Resource
private Environment env;
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getRequiredProperty(PROPERTY_NAME_DATABASE_DRIVER));
dataSource.setUrl(env.getRequiredProperty(PROPERTY_NAME_DATABASE_URL));
dataSource.setUsername(env.getRequiredProperty(PROPERTY_NAME_DATABASE_USERNAME));
dataSource.setPassword(env.getRequiredProperty(PROPERTY_NAME_DATABASE_PASSWORD));
return dataSource;
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSource());
entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);
entityManagerFactoryBean.setPackagesToScan(env.getRequiredProperty(PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN));
entityManagerFactoryBean.setJpaProperties(hibProperties());
return entityManagerFactoryBean;
}
private Properties hibProperties() {
Properties properties = new Properties();
properties.put(PROPERTY_NAME_HIBERNATE_DIALECT, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_DIALECT));
properties.put(PROPERTY_NAME_HIBERNATE_SHOW_SQL, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_SHOW_SQL));
properties.put("hibernate.hbm2ddl.auto", "create-drop");
return properties;
}
@Bean
public JpaTransactionManager transactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
return transactionManager;
}
@Bean
public ResourceBundleMessageSource messageSource() {
ResourceBundleMessageSource source = new ResourceBundleMessageSource();
source.setBasename(env.getRequiredProperty("message.source.basename"));
source.setUseCodeAsDefaultMessage(true);
return source;
}
@Bean
public InternalResourceViewResolver getInternalResourceViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
@Bean
public WebContentInterceptor webContentInterceptor() {
WebContentInterceptor interceptor = new WebContentInterceptor();
interceptor.setCacheSeconds(0);
interceptor.setUseExpiresHeader(true);
interceptor.setUseCacheControlHeader(true);
interceptor.setUseCacheControlNoStore(true);
return interceptor;
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
registry.addResourceHandler("/lib/**").addResourceLocations("/WEB-INF/lib/");
registry.addResourceHandler("/scripts/**").addResourceLocations("/WEB-INF/scripts/");
registry.addResourceHandler("/styles/**").addResourceLocations("/WEB-INF/styles/");
registry.addResourceHandler("/fonts/**").addResourceLocations("/WEB-INF/fonts/");
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(webContentInterceptor());
}
}
Web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://ift.tt/ra1lAU"
xmlns="http://ift.tt/nSRXKP" xmlns:web="http://ift.tt/LU8AHS"
xsi:schemaLocation="http://ift.tt/nSRXKP http://ift.tt/1eWqHMP"
version="3.0">
<display-name>jukebox</display-name>
<!-- filters needed for put requests, known bug with spring rest -->
<filter>
<filter-name>HttpPutFormContentFilter</filter-name>
<filter-class>org.springframework.web.filter.HttpPutFormContentFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HttpPutFormContentFilter</filter-name>
<url-pattern>/*</url-pattern>
<servlet-name>dispatcher</servlet-name>
</filter-mapping>
</web-app>
Aucun commentaire:
Enregistrer un commentaire