-
Notifications
You must be signed in to change notification settings - Fork 4
Proposal #1: ServiceBox action servlet with Spring Framework
Include Spring Framework on the project.
Alejandro Díaz (alediator)
ServiceBox 1.4, MapStore 1.5
Choose one of: Under Discussion, In Progress, Completed, Rejected, Deferred
Improve this application to fix mapstore #138 issue
Include the Spring Framework dependencies and generalize Servlets in a specific ServiceBox action servlet to allow to envelop requests in order to filter with specific callbacks configurable with a property overrider and the servicebox.properties.
The first callback is a file uploader one to fix mapstore #138 and is going to change the Servlets:
- FileUploader
- KMZUploader
- FileDownloader
- HTTPWebGISFileDownload
- HTTPWebGISFileUpload
- HTTPWebGISSave
- UploadCanvas
The ServiceBoxActionServlet reads the Spring context on the Servlet initialization and save the ActionHandler:
/**
* Init method of the servlet. Don't forgot override it on the actions and
* change the action name
*/
public void init(ServletConfig servletConfig) throws ServletException {
super.init(servletConfig);
String appPropertyFile = getServletContext().getInitParameter(
PROPERTY_FILE_PARAM);
InputStream inputStream = ServiceBoxActionServlet.class
.getResourceAsStream(appPropertyFile);
try {
properties.load(inputStream);
ServletContext context = getServletContext();
WebApplicationContext wac = WebApplicationContextUtils
.getRequiredWebApplicationContext(context);
String actionHandler = DEFAULT_ACTION_HANDLER;
if (actionName != null
&& properties != null
&& properties.containsKey(actionName + "."
+ DEFAULT_ACTION_HANDLER)) {
actionHandler = properties.getProperty(actionName + "."
+ DEFAULT_ACTION_HANDLER);
}
serviceBoxActionHandler = (ServiceBoxActionHandler) wac
.getBean(actionHandler);
} catch (IOException e) {
if (LOGGER.isLoggable(Level.SEVERE)) {
LOGGER.log(Level.SEVERE,
"Error encountered while processing properties file", e);
}
} finally {
try {
if (inputStream != null)
inputStream.close();
} catch (IOException e) {
if (LOGGER.isLoggable(Level.SEVERE))
LOGGER.log(Level.SEVERE,
"Error building the action configuration ", e);
throw new ServletException(e.getMessage());
}
}
}
The ServiceBoxActionHandler execute each callback configured on the GET and POST actions and call and return the last ServiceBoxActionParameters (from the last callback)
/**
* Handle a GET request
*
* @param request
* @param response
*
* @return ServiceBoxActionParameters
*
* @throws IOException
*/
public ServiceBoxActionParameters doGet(HttpServletRequest request,
HttpServletResponse response) throws IOException {
ServiceBoxActionParameters callbackResult = null;
if (callbacks != null) {
for (Callback callback : callbacks) {
callbackResult = callback.onGet(request, response,
callbackResult);
if (!callbackResult.isSuccess()) {
// not success: return false
break;
}
}
}
return callbackResult;
}
this callback includes the status of the callback execution and some parameters used inside each callback to allow it read request only one time and write rules in different callbacks.
public class ServiceBoxActionParameters {
private boolean success = false;
private List<FileItem> items;
private Map<String, Object> extensions;
To use it, change a Servlet and extend ServiceBoxActionServlet
/**
* Servlet implementation class FileUploader
*/
public class FileUploader extends ServiceBoxActionServlet {
and change the doGet and doPost methods:
protected void doPostAction(HttpServletRequest request,
HttpServletResponse response, ServiceBoxActionParameters actionParameters) throws ServletException, IOException {
// get parameter name
String moveFile = request.getParameter("moveFile");
String type = request.getParameter("type");
String fileToMoveName = request.getParameter("zipName");
List<FileItem> items = null;
File fileToMove = null;
try {
// create a file with a random name
String uuid = UUID.randomUUID().toString();
// File items are read only one time. Check if already exists on the actionParameters
if(actionParameters != null
&& actionParameters.isSuccess()
&& actionParameters.getItems() != null){
items = actionParameters.getItems();
// see http://commons.apache.org/fileupload/using.html
}else if (ServletFileUpload.isMultipartContent(request)) {
// Create a factory for disk-based file items
FileItemFactory factory = new DiskFileItemFactory();
// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload(factory);
// Parse the request
items = upload.parseRequest(request);
}
// Process the uploaded items
if (items != null) {
the default callback can be configured on the property overrider:
# File upload callback configuration
fileUploadCallback.callbackConfiguration.maxSize=1000024
fileUploadCallback.callbackConfiguration.maxItems=100
fileUploadCallback.callbackConfiguration.tempFolder=/tmp
fileUploadCallback.callbackConfiguration.buffSize=1024
Then, if you send more than 100 items, the server return a message like this: { "success":false, "errorMessage":"Max items size exceeded (expected: '100', found: '200')."}
or if one of your uploaded files exceed the size limit the message is: { "success":false, "errorMessage":" Max item size exceeded (expected: '100024', found: '141357' on item 'test.kml')."}
This section should contain feedback provided by members who may have a problem with the proposal.
This change needs to improve a litle bit the widgets on MapStore to read the error messages instead, but is compatible (it only knows that there are an error on the file upload, but it doesn't read the error message).
Alejandro Díaz: +1