Spring ajax send list of objects from controller to jsp - ajax

I am trying to send send list of objects which I get from database to my JSP. I managed to successfully send data from JSP to my controller. Method inside my controller takes that parameter, fills List (I checked it in debug mode) and controller returns that list.
#RequestMapping(value="/test.html", method=RequestMethod.GET, produces="application/json")
public #ResponseBody List<ModelVechicle> fetchListModelById(#RequestParam Integer number) {
System.out.println(number);
List<ModelVechicle> modelList = vechicleService.fetchModelById(number);
return modelList;
}
When I try to get that List on my JSP, I get
HTTP Status 406 -
type Status report
message
description The resource identified by this request is only capable of generating
responses with characteristics not acceptable according to the request "accept" headers.
Apache Tomcat/8.0.32
Here is my JSP with AJAX code
<script type="text/javascript">
$(document).ready(function(){
$("#brand").change(onSelectChange);
});
function onSelectChange() {
var selected = $("#brand option:selected");
var output = "";
var number = parseInt(selected.val());
$.ajax({
type: "GET",
url: "test.html",
dataType : 'json',
data: ({number: number}),
success: function(response){
$('#result').html("");
var obj = JSON.parse(response);
$('#result').html(obj.modelName);
},
error: function(xhr,e){
alert('Error while request..'+xhr.responseText);
}
});
if(selected.val() != 0){
output = "You selected brand " + selected.text();
}
$("#output").html(number);
}
Also here is my ModelVechicle class, that is the class which objects I am adding into List:
#Entity
#Table(name = "CARDEALERSHIP.MODEL")
public class ModelVechicle implements Serializable {
private static final long serialVersionUID = 7420515051961158192L;
#Id
#Column(name = "ID")
private Integer modelId;
#Column(name = "MODELNAME")
private String modelName;
#ManyToOne
#JoinColumn(name = "BRANDID")
private Brand brand;
public ModelVechicle(Integer modelId, String modelName, Brand brand) {
super();
this.modelId = modelId;
this.modelName = modelName;
this.brand = brand;
}
public ModelVechicle() {}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((brand == null) ? 0 : brand.hashCode());
result = prime * result + ((modelId == null) ? 0 : modelId.hashCode());
result = prime * result + ((modelName == null) ? 0 : modelName.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ModelVechicle other = (ModelVechicle) obj;
if (brand == null) {
if (other.brand != null)
return false;
} else if (!brand.equals(other.brand))
return false;
if (modelId == null) {
if (other.modelId != null)
return false;
} else if (!modelId.equals(other.modelId))
return false;
if (modelName == null) {
if (other.modelName != null)
return false;
} else if (!modelName.equals(other.modelName))
return false;
return true;
}
public Integer getModelId() {
return modelId;
}
public void setModelId(Integer modelId) {
this.modelId = modelId;
}
public String getModelName() {
return modelName;
}
public void setModelName(String modelName) {
this.modelName = modelName;
}
public Brand getBrand() {
return brand;
}
public void setBrand(Brand brand) {
this.brand = brand;
}
Can somebody please explain me what to do in order to get the List dynamically to JSP page, and display List members properly?
EDIT: Here is my web.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>CarDealership</display-name>
<welcome-file-list>
<welcome-file>addVechicle.html</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>springDispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/dispatchers.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springDispatcher</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/app-config.xml
</param-value>
</context-param>
</web-app>

As of Spring 3.2+, the content negotiation has other facts in account prior to eval Accept header:
From https://spring.io/blog/2013/05/11/content-negotiation-using-spring-mvc:
Enabling Content Negotiation in Spring MVC
Spring supports a couple of conventions for selecting the format
required: URL suffixes and/or a URL parameter. These work alongside
the use of Accept headers. As a result, the content-type can be
requested in any of three ways. By default they are checked in this
order:
Add a path extension (suffix) in the URL. So, if the incoming URL is something like http://myserver/myapp/accounts/list.html then HTML
is required. For a spreadsheet the URL should be
http://myserver/myapp/accounts/list.xls. The suffix to media-type
mapping is automatically defined via the JavaBeans Activation
Framework or JAF (so activation.jar must be on the class path).
A URL parameter like this: http://myserver/myapp/accounts/list?format=xls. The name of the
parameter is format by default, but this may be changed. Using a
parameter is disabled by default, but when enabled, it is checked
second.
Finally the Accept HTTP header property is checked. This is how HTTP is > actually defined to work, but, as previously mentioned, it can
be problematic to use.
That actually means that if you map a #Controller method with a .htm(l) suffix, it is intended to return html and won't return json nor any other format even if you sent other format as Accept header.
I allways map my controllers as .htm and had to change the way I used to map #ResponseBody annotated methods when I upgraded to Spring 3.2 and newer.
EDIT:
After seeing your web.xml, as I supposed, you are mapping every .html suffix request to the dispatcher servlet:
`<servlet-mapping>
<servlet-name>springDispatcher</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>`
I figure that now the #RequestMapping in your controller is like this:
#RequestMapping(value="/test", method=RequestMethod.GET, produces="application/json")
public #ResponseBody List<ModelVechicle> fetchListModelById(#RequestParam Integer number) {
As /test does not match .html suffix, request is not arriving to springDispatcher, and that's exactly why you are getting a 404.
Now, options to fix this:
1) Add a new mapping in the web.xml which matches this controller:
<servlet-mapping>
<servlet-name>springDispatcher</servlet-name>
<url-pattern>*.html</url-pattern>
<url-pattern>*/test</url-pattern>
</servlet-mapping>
This way you would be forced to include any new non html returning method. Not seems usable for me.
2) Map all incoming requests to dispatcherServlet
<servlet-mapping>
<servlet-name>springDispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
I don't really like this option, I prefer to filter what I really want to reach the dispatcher servlet.
3) Find a new matching pattern for this kind of requests. I allways publish some kind of generic suffix, which will not be catched by JAF, such as *.service:
<servlet-mapping>
<servlet-name>springDispatcher</servlet-name>
<url-pattern>*.html</url-pattern>
<url-pattern>*.service</url-pattern>
</servlet-mapping>
So in Controller methods which return XML or JSON (or any other format, depending only of the Accept header), I map like this:
#RequestMapping(value="/test.service", method=RequestMethod.GET, produces="application/json")
public #ResponseBody List<ModelVechicle> fetchListModelById(#RequestParam Integer number) {
4) You could as well publish all this kind of #ResponseBody controller method using a 'http://com.xxx.yyy/myApp/service/resource' pattern and use /service/ as servlet mapping in web.xml
<servlet-mapping>
<servlet-name>springDispatcher</servlet-name>
<url-pattern>*.html</url-pattern>
<url-pattern>/service/</url-pattern>
</servlet-mapping>

Related

How do I log security activities for request and different event in spring?

I have implemented spring security oauth2 to protect different services.
Now I need to log client ip, client id, request service, request URL and Event type like "Authentication Failure", "Authorization failure" and so on.
I came up with following
public class Events implements ApplicationListener<ApplicationEvent>{
private static Logger log = LoggerFactory.getLogger(Events.class);
#Override
public void onApplicationEvent(ApplicationEvent appEvent) {
if (appEvent instanceof AuthenticationSuccessEvent) {
AuthenticationSuccessEvent event = (AuthenticationSuccessEvent) appEvent;
long timestamp = event.getTimestamp();
User user = (User) event.getAuthentication().getPrincipal();
System.out.println("client " + user.getUsername() + " has been authenticated successfully.");
UsernamePasswordAuthenticationToken source = (UsernamePasswordAuthenticationToken) event.getSource();
WebAuthenticationDetails details = (WebAuthenticationDetails) source.getDetails();
System.out.println("remote ip is " + details.getRemoteAddress());
}
if (appEvent instanceof AuthorizationFailureEvent) {
//TODO
((AuthorizationFailureEvent) appEvent).getAccessDeniedException();
}
if (appEvent instanceof AbstractAuthenticationFailureEvent) {
System.out.println("Sorry, authenticated for client " + appEvent.getSource().toString() + " failure.");
}
}
}
Because the request is asynchronous, I don't know how to get request from context. If I can get HttpServletRequest request, I can get almost every thing.
Refer to this. I have add RequestContextFilter in web.xml.
<filter>
<filter-name>requestContextFilter</filter-name>
<filter-class>org.springframework.web.filter.RequestContextFilter</filter-class>
<init-param>
<param-name>threadContextInheritable</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>requestContextFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
It works well.

File upload in Struts2 along with the Spring CSRF token

I use,
Spring Framework 4.0.0 RELEASE (GA)
Spring Security 3.2.0 RELEASE (GA)
Struts 2.3.16
In which, I use an in-built security token to guard against CSRF attacks.
<s:form namespace="/admin_side"
action="Category"
enctype="multipart/form-data"
method="POST"
validate="true"
id="dataForm"
name="dataForm">
<s:hidden name="%{#attr._csrf.parameterName}"
value="%{#attr._csrf.token}"/>
</s:form>
It is a multipart request in which the CSRF token is unavailable to Spring security unless MultipartFilter along with MultipartResolver is properly configured so that the multipart request is processed by Spring.
MultipartFilter in web.xml is configured as follows.
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext.xml
/WEB-INF/spring-security.xml
</param-value>
</context-param>
<filter>
<filter-name>MultipartFilter</filter-name>
<filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class>
</filter>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>MultipartFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>AdminLoginNocacheFilter</filter-name>
<filter-class>filter.AdminLoginNocacheFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AdminLoginNocacheFilter</filter-name>
<url-pattern>/admin_login/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>NoCacheFilter</filter-name>
<filter-class>filter.NoCacheFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>NoCacheFilter</filter-name>
<url-pattern>/admin_side/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<description>Description</description>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
<init-param>
<param-name>struts.devMode</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
And in applicationContext.xml, MultipartResolver is registered as follows.
<bean id="filterMultipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="-1" />
</bean>
The CSRF token is now received by Spring security but doing so incurs another problem in Struts.
Uploaded file(s) is now null in Struts action classes like as follows.
#Namespace("/admin_side")
#ResultPath("/WEB-INF/content")
#ParentPackage(value="struts-default")
public final class CategoryAction extends ActionSupport implements Serializable, ValidationAware, ModelDriven<Category>
{
private File fileUpload;
private String fileUploadContentType;
private String fileUploadFileName;
private static final long serialVersionUID = 1L;
//Getters and setters.
//Necessary validators as required.
#Action(value = "AddCategory",
results = {
#Result(name=ActionSupport.SUCCESS, type="redirectAction", params={"namespace", "/admin_side", "actionName", "Category"}),
#Result(name = ActionSupport.INPUT, location = "Category.jsp")},
interceptorRefs={
#InterceptorRef(value="defaultStack", "validation.validateAnnotatedMethodOnly", "true"})
})
public String insert(){
//fileUpload, fileUploadContentType and fileUploadFileName are null here after the form is submitted.
return ActionSupport.SUCCESS;
}
#Action(value = "Category",
results = {
#Result(name=ActionSupport.SUCCESS, location="Category.jsp"),
#Result(name = ActionSupport.INPUT, location = "Category.jsp")},
interceptorRefs={
#InterceptorRef(value="defaultStack", params={ "validation.validateAnnotatedMethodOnly", "true", "validation.excludeMethods", "load"})})
public String load() throws Exception{
//This method is just required to return an initial view on page load.
return ActionSupport.SUCCESS;
}
}
This happens because to my guess, the multipart request is already processed and consumed by Spring hence, it is not available to Struts as a multipart request and therefore, the file object in a Struts action class is null.
Is there a way to get around this situation? Otherwise, I have now left with the only option to append the token to a URL as a query-string parameter which is highly discouraged and not recommended at all.
<s:form namespace="/admin_side"
action="Category?%{#attr._csrf.parameterName}=%{#attr._csrf.token}"
enctype="multipart/form-data"
method="POST"
validate="true"
id="dataForm"
name="dataForm">
...
<s:form>
Long story short : How to get files in a Struts action class, if Spring is made to process a mulipart request? On the other hand, if Spring is not made to process a multipart request then, it lakes the security token. How to overcome this situation?
It seems your best bet is to create a custom MultiPartRequest implementation that delegates to Spring's MultipartRequest. Here is an example implementation:
sample/SpringMultipartParser.java
package sample;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.Map.Entry;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.dispatcher.multipart.MultiPartRequest;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.util.WebUtils;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
public class SpringMultipartParser implements MultiPartRequest {
private static final Logger LOG = LoggerFactory.getLogger(MultiPartRequest.class);
private List<String> errors = new ArrayList<String>();
private MultiValueMap<String, MultipartFile> multipartMap;
private MultipartHttpServletRequest multipartRequest;
private MultiValueMap<String, File> multiFileMap = new LinkedMultiValueMap<String, File>();
public void parse(HttpServletRequest request, String saveDir)
throws IOException {
multipartRequest =
WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class);
if(multipartRequest == null) {
LOG.warn("Unable to MultipartHttpServletRequest");
errors.add("Unable to MultipartHttpServletRequest");
return;
}
multipartMap = multipartRequest.getMultiFileMap();
for(Entry<String, List<MultipartFile>> fileEntry : multipartMap.entrySet()) {
String fieldName = fileEntry.getKey();
for(MultipartFile file : fileEntry.getValue()) {
File temp = File.createTempFile("upload", ".dat");
file.transferTo(temp);
multiFileMap.add(fieldName, temp);
}
}
}
public Enumeration<String> getFileParameterNames() {
return Collections.enumeration(multipartMap.keySet());
}
public String[] getContentType(String fieldName) {
List<MultipartFile> files = multipartMap.get(fieldName);
if(files == null) {
return null;
}
String[] contentTypes = new String[files.size()];
int i = 0;
for(MultipartFile file : files) {
contentTypes[i++] = file.getContentType();
}
return contentTypes;
}
public File[] getFile(String fieldName) {
List<File> files = multiFileMap.get(fieldName);
return files == null ? null : files.toArray(new File[files.size()]);
}
public String[] getFileNames(String fieldName) {
List<MultipartFile> files = multipartMap.get(fieldName);
if(files == null) {
return null;
}
String[] fileNames = new String[files.size()];
int i = 0;
for(MultipartFile file : files) {
fileNames[i++] = file.getOriginalFilename();
}
return fileNames;
}
public String[] getFilesystemName(String fieldName) {
List<File> files = multiFileMap.get(fieldName);
if(files == null) {
return null;
}
String[] fileNames = new String[files.size()];
int i = 0;
for(File file : files) {
fileNames[i++] = file.getName();
}
return fileNames;
}
public String getParameter(String name) {
return multipartRequest.getParameter(name);
}
public Enumeration<String> getParameterNames() {
return multipartRequest.getParameterNames();
}
public String[] getParameterValues(String name) {
return multipartRequest.getParameterValues(name);
}
public List getErrors() {
return errors;
}
public void cleanUp() {
for(List<File> files : multiFileMap.values()) {
for(File file : files) {
file.delete();
}
}
// Spring takes care of the original File objects
}
}
Next you need to ensure that Struts is using it. You can do this in your struts.xml file as shown below:
struts.xml
<constant name="struts.multipart.parser" value="spring"/>
<bean type="org.apache.struts2.dispatcher.multipart.MultiPartRequest"
name="spring"
class="sample.SpringMultipartParser"
scope="default"/>
WARNING: It is absolutely necessary to ensure that a new instance of MultipartRequest is created for every multipart request by properly setting the scope of the bean otherwise you will see race conditions.
After doing this, your Struts actions will have the file information added just as it was before. Keep in mind that validation of file (i.e. file size) is now done with filterMultipartResolver instead of Struts.
Using Themes to auto include the CSRF token
You might consider creating a custom theme so that you can automatically include the CSRF token in forms. For more information on how to do this see http://struts.apache.org/release/2.3.x/docs/themes-and-templates.html
Complete Example on Github
You can find a complete working sample on github at https://github.com/rwinch/struts2-upload
The form encoding multipart/formdata is meant to be used for file upload scenarios, this is according to the W3C documentation:
The content type "multipart/form-data" should be used for submitting
forms that contain files, non-ASCII data, and binary data.
The MultipartResolver class expects a file upload only, and not other form fields, this is from the javadoc:
/**
* A strategy interface for multipart file upload resolution in accordance
* with RFC 1867.
*
*/
So this is why adding the CSRF as a form field would not work, the usual way to secure file upload requests against CSRF attacks is to send the CSRF token in a HTTP request header instead of the POST body. For that you need to make it an ajax POST.
For a normal POST there is no way to do this, see this answer. Either make the POST an ajax request and add the header with some Javascript, or send the CSRF token as a URL parameter as you mentioned.
If the CSRF token is frequently regenerated as it should ideally be between requests, then sending it in as request parameter is less of a problem and might be acceptable.
On the server side, you would need to configure the CSRF solution to read the token from the header, this is usually foreseen by the CSRF solution being used.
At a first glance your configuration looks correct to me. I therefore think that the problem might be some tiny bit of misconfiguration somewhere.
I faced a similar problem with Spring MVC instead of Struts, which I was able to solve with help from the Spring Security team. For full details see this answer.
You may also compare your set up with a working sample available on Github. I have tested this on Tomcat 7, JBoss AS 7, Jetty and Weblogic.
If these do not work, it will be helpful if you can create a single controller, single page application with your configuration that demonstrates the problem and upload it somewhere.
I'm not a Struts user, but I think you can use the fact that the Spring MultipartFilter wraps the request in a MultipartHttpServletRequest.
First get a hold of the HttpServletRequest, in Struts I think you can do it something like this:
ServletRequest request = ServletActionContext.getRequest();
Then retreive the MultipartRequest out of it, wrapping up wrappers if necessary:
MultipartRequest multipart = null;
while (multipart == null)
{
if (request instanceof MultipartRequest)
multipart = (MultipartRequest)request;
else if (request instanceof ServletRequestWrapper)
request = ((ServletRequestWrapper)request).getRequest();
else
break;
}
If this request was a multipart, get the file by the form input name:
if (multipart != null)
{
MultipartFile mf = multipart.getFile("forminputname");
// do your stuff
}

#RequestMapping not working for .jsp

here is the url-pattern in web.xml
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Here is my controller
#Controller
public class HelloController
{
#RequestMapping("/*.km")
public String handleKm()
{
System.out.println("km ext called");
return "aaa";
}
#RequestMapping("/*.jsp")
public String handleJsp()
{
System.out.println("jsp pages called");
return "bbb";
}
}
while accessing the url with /requestMapping/a.km , it is works, calls the handleKm() method.but with /requestMapping/a.jsp , it should call handleJsp().but it does not work. result : HTTP Status 404 - /requestMapping/a.jsp.
why ??
If I chane the url-pattern from "/" to "/*" , although both method are called , but dont get to the appropriate pages.
May be the "org.springframework.web.servlet.view.InternalResourceViewResolver" is not working .
Check out this related SO post (possibly a duplicate). I think the .jsp extension is confusing the dispatcher servlet. Try using an extension that isn't .jsp and see if that works.

Spring REST DELETE example error

I want to implement Spring REST methods. I tried Get and it works:
#RequestMapping(value = "{systemId}", method = RequestMethod.GET)
public
#ResponseBody
Configuration getConfigurationInJSON(HttpServletResponse response, #PathVariable long systemId) throws IOException {
if (configurationMap.containsKey(systemId)) {
return configurationMap.get(systemId);
} else {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return null;
}
}
However when I want to implement DELETE it doesn't. My method is that:
#RequestMapping(value = "{systemId}", method = RequestMethod.DELETE)
public void deleteConfiguration(HttpServletResponse response, #PathVariable long systemId) throws IOException {
if (configurationMap.containsKey(systemId)) {
configurationMap.remove(systemId);
response.setStatus(HttpServletResponse.SC_FOUND);
} else {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
}
}
My web.xml as follows:
mvc-dispatcher
org.springframework.web.servlet.DispatcherServlet
1
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/ui/*</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
Command that works when I try with Curl for GET:
curl http://localhost:8080/ui/webapp/conf/1
Command that doesn't work when I try with Curl for DELETE:
curl -x delete http://localhost:8080/ui/webapp/conf/1
Second command gives that error after a time later at curl:
curl: (7) couldn't connect to host
There is no error at Tomcat side and at debug it doesn't enter the delete method body.
Any ideas?
Try
curl -X DELETE http://localhost:8080/ui/webapp/conf/1
with uppercase DELETE and uppercase X

Smartgwt with RestDataSource and SpringController

I have been stuck at this for a while. I have a smartgwt widget listgrid tied to a restdatasource. I have mapped its URLs to my spring services. However I cannot figure out how to retrieve the JSON dsrequest on spring server side. Even my dispatcher servlet does not contain the params.
My restdatasource is as follows:
RestDataSource myDS = new RestDataSource() {
#Override
protected Object transformRequest(DSRequest dsRequest) {
dsRequest.setContentType("application/json");
JavaScriptObject jso = dsRequest.getData();
String s1 = JSON.encode(jso);
return s1;
// return super.transformRequest(dsRequest);
}
#Override
protected void transformResponse(DSResponse response, DSRequest request, Object data) {
super.transformResponse(response, request, data);
}
};
Then on this datasource set the operations as follows:
// set the operation on the datasource
OperationBinding fetch = new OperationBinding();
fetch.setOperationType(DSOperationType.FETCH);
fetch.setDataProtocol(DSProtocol.POSTMESSAGE);
OperationBinding add = new OperationBinding();
add.setOperationType(DSOperationType.ADD);
add.setDataProtocol(DSProtocol.POSTMESSAGE);
OperationBinding update = new OperationBinding();
update.setOperationType(DSOperationType.UPDATE);
update.setDataProtocol(DSProtocol.POSTPARAMS);
OperationBinding remove = new OperationBinding();
remove.setOperationType(DSOperationType.REMOVE);
remove.setDataProtocol(DSProtocol.POSTMESSAGE);
myDS.setOperationBindings(fetch, add, update, remove);
myDS.setDataFormat(DSDataFormat.JSON);
// myDS.setDataProtocol(DSProtocol.POSTMESSAGE);
Set some fields in the datasource:
// set the values for the datasource
DataSourceTextField Id = new DataSourceTextField("Id", "Id");
Id.setPrimaryKey(true);
Id.setCanEdit(false);
DataSourceTextField name= new DataSourceTextField("name", "Name");
name.setCanEdit(false);
DataSourceTextField employeeType= new DataSourceTextField("employeeType", "employeeType");
employeeType.setCanEdit(true);
employeeType.setValueMap("Manager", "Associate", "Contractor");
Set these fields to the datasource:
myDS.setFields(Id, name,employeeType);
myDS.setFetchDataURL("/rest/myservice/fetch");
myDS.setAddDataURL("/rest/myservice/add");
myDS.setUpdateDataURL("/rest/myservice/update");
myDS.setRemoveDataURL("/rest/myservice/remove");
So in the case that the user changes the employeeType (because it's a dropdown), an update request is sent. I send the JSON string to the server configured as below:
#Controller
#RequestMapping("/myservice")
public class MyService {
...fetch
...update
#RequestMapping(value="/update", method=RequestMethod.POST)
#ResponseBody
public String update()
{
}
I am failing to understand how to retrieve the (JSON) dsrequest because even my DispatcherServlet does not have the parameters (even if I use POSTPARAMS). The developer console shows the request made correctly but I don't receive anything on the server side.
My spring servlet is configured as below in web.xml:
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup> </servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
I think I am missing something obvious but I can't locate it. Do I use #PathVariable or RequestParams?
Found my own answer. Hope this helps someone.
update.setDataProtocol(DSProtocol.POSTPARAMS);
to
update.setDataProtocol(DSProtocol.POSTMESSAGE);
#Override
protected Object transformRequest(DSRequest dsRequest) {
JavaScriptObject jso = dsRequest.getData();
String s1 = JSON.encode(jso);
return s1;
}
#RequestMapping(value="/update", method=RequestMethod.POST)
#ResponseBody public String update(#RequestBody String json) { }

Resources