Warning |
---|
|
In Stripes 1.7 there is a much better solution to all of this using @RestActionBean. Here's the RESTful Calculator Example: |
I used Stripes 1.5 to communicate with an angular 1.5 client which posts with a JSON body by wrapping the HTTPServletRequest.
...
Code Block |
---|
language | java |
---|
title | JsonRequest |
---|
collapse | true |
---|
|
package com.example.util;
import java.io.BufferedReader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.http.MediaType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* Used to wrap an {@link HttpServletRequest} with a {@link MediaType#APPLICATION_JSON} header so that the body of the request can be read as a JSON object and so that Stripes can still have access to
* request parameters.
*/
public class JsonRequest extends HttpServletRequestWrapper {
private Map<String, String[]> parameters = new HashMap<String, String[]>();
public JsonRequest(HttpServletRequest request) throws Exception {
super(request);
buildParameters(request);
}
/**
* Read the body of the request as JSON then map the root field names as parameter keys.
*/
private void buildParameters(HttpServletRequest request) throws Exception {
StringBuilder builder = new StringBuilder();
String line;
BufferedReader reader = request.getReader();
while ((line = reader.readLine()) != null) {
builder.append(line);
}
String body = builder.toString();
ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readValue(body, JsonNode.class);
Iterator<String> fieldNames = root.fieldNames();
while (fieldNames.hasNext()) {
String key = fieldNames.next();
JsonNode value = root.get(key);
parameters.put(key, new String[] { value.toString() });
}
}
@Override
public String getParameter(String name) {
String value = null;
Map<String, String[]> mergedParams = getParameterMap();
String[] values = mergedParams.get(name);
if (ArrayUtils.getLength(values) > 0) {
value = values[0];
}
return value;
}
@Override
public Map<String, String[]> getParameterMap() {
Map<String, String[]> parentParameters = super.getParameterMap();
Map<String, String[]> mergedParams = new HashMap<String, String[]>(parentParameters.size() + parameters.size());
mergedParams.putAll(parentParameters);
mergedParams.putAll(parameters);
return mergedParams;
}
@Override
public String[] getParameterValues(String name) {
Map<String, String[]> mergedParams = getParameterMap();
return mergedParams.get(name);
}
} |
Example ActionBean
Code Block |
---|
language | java |
---|
title | StatsWS |
---|
collapse | true |
---|
|
package com.example.stats;
import java.util.Date;
import org.apache.commons.lang3.StringUtils;
import com.example.stats.StatsService;
import com.example.util.JsonTypeConverter;
import com.example.util.BaseWS;
import com.example.util.JsonResolution;
import net.sourceforge.stripes.action.DefaultHandler;
import net.sourceforge.stripes.action.Resolution;
import net.sourceforge.stripes.action.UrlBinding;
import net.sourceforge.stripes.integration.spring.SpringBean;
import net.sourceforge.stripes.validation.SimpleError;
import net.sourceforge.stripes.validation.Validate;
import net.sourceforge.stripes.validation.ValidationErrors;
import net.sourceforge.stripes.validation.ValidationMethod;
/**
* Stats web service.
*
* Loads global stats, and if a date range is provided loads the interval stats as well.
*/
@UrlBinding("/ws/stats")
public class StatsWS extends BaseWS {
private String START_DATE_FIELD_NAME = "params.startDate";
private String END_DATE_FIELD_NAME = "params.endDate";
@SpringBean
private StatsService statsService;
private StatsParamsRequest params;
private Date startDate; // populated during validation
private Date endDate; // populated during validation
@Validate(required = true, converter = JsonTypeConverter.class)
public void setParams(StatsParamsRequest params) {
this.params = params;
}
@DefaultHandler
public Resolution reply() {
Stats global = statsService.loadGlobalStats();
Stats interval = null;
if (startDate != null && endDate != null) {
interval = statsService.loadIntervalStats(startDate, endDate);
}
StatsReply reply = new StatsReply();
reply.setGlobal(global);
reply.setInterval(interval);
return new JsonResolution(reply);
}
@ValidationMethod
public void validateDates(ValidationErrors errors) {
if (params == null) {
errors.add("params", new SimpleError("params is null"));
}
boolean hasStart = !StringUtils.isEmpty(params.getStartDate());
boolean hasEnd = !StringUtils.isEmpty(params.getEndDate());
if (hasStart && hasEnd) {
startDate = parseIso8601Date(params.getStartDate(), START_DATE_FIELD_NAME, errors);
endDate = parseIso8601Date(params.getEndDate(), END_DATE_FIELD_NAME, errors);
}
else if (hasStart ^ hasEnd) { // both dates can be null, but not just one of them
errors.add(START_DATE_FIELD_NAME, new SimpleError(StatsService.MSG_START_END_DATES));
}
}
} |
...