Action based controller using reflections - java

I'm modeling a controller reflection based. I would like to know if you agree my implementation and what could to be enhanced.
I'm starting with reflection and I would like to know if I'm using good practices.
Sample: www.sample.com/Main?mvc=user/edit/5
See it:
public class StartController extends HttpServlet {
#Override
public void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
String vars = req.getParameter("mvc");
ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
MainController main = new MainController();
main.RESTProcess(req, resp, context, vars);
}
}
public class MainController extends Controller {
public void RESTProcess(HttpServletRequest req, HttpServletResponse resp, ApplicationContext context, String vars)
throws IOException, ServletException
{
String[] url;
int nvars;
String controller = null;
String action = null;;
String[] params = null;
int i;
int n;
String controllerName;
String actionName;
if(vars == null || "".equals(vars.trim()))
{
this.redirect(resp,"home");
}
else
{
url = vars.split("/");
nvars = url.length;
if(nvars > 0)
{
controller = url[0].trim(); //users
if(nvars > 1)
{
action = url[1].trim(); //edit
if(nvars > 2)
{
n = 0;
params = new String[nvars - 2]; //array[0] = 5 (iduser)
for(i = 2; i < nvars; i++)
{
params[n] = url[i];
n++;
}
}
}
controllerName = this.getFirstUpper(controller) + "Controller"; //HomeController, UserController pattern
if(!controllerName.equals("Controller"))
{
actionName = "action" + this.getFirstUpper(action); //actionIndex, actionEdit pattern
if(!action.equals("action"))
{
try
{
Class classe = Class.forName("com.sample.controller." + controllerName);
try
{
Constructor c = classe.getConstructor(HttpServletRequest.class, HttpServletResponse.class, String[].class);
try
{
Object obj = c.newInstance(req, resp, context, params);
Method m = classe.getMethod(actionName, null);
m.invoke(obj, null);
System.out.println(obj.toString());
}
catch (Exception e)
{
e.printStackTrace();
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
}
else
{
this.redirect(resp,"home");
}
}
}
public String getFirstUpper(String str)
{
Integer x = str.length();
str = str.substring(0,1).toUpperCase().concat(str.substring(1, x));
return str;
}
}
public class UserController extends Controller {
private HttpServletRequest req;
private HttpServletResponse resp;
private ApplicationContext context;
private String[] params;
public UserController(HttpServletRequest req, HttpServletResponse resp, ApplicationContext context, String[] params)
{
this.req = req;
this.resp = resp;
this.context = context;
this.params = params;
}
public void actionEdit()
{
Long id = Long.valueOf(this.params[0]);
System.out.println("/home/edit");
}
}

Related

How to skip null value in Chain of Responsibilities?

I understand the responsibility chain pattern. And I have such a question. As can be seen from my chain of responsibility, if the method does not return the locale to me, then it returns null. How can I go to the next item in the chain if it returns null?
public abstract class StandardLocaleHandler {
protected StandardLocaleHandler localeHandler;
public StandardLocaleHandler() {
this.localeHandler = null;
}
protected abstract Locale getTrueLocale(HttpServletRequest req, HttpServletResponse resp, List<String> localeList, String defaultLocale, Integer cookieAge);
public void setNext(StandardLocaleHandler localeHandler) {
this.localeHandler = localeHandler;
}
public StandardLocaleHandler getNext() {
return localeHandler;
}
}
public class GetLocaleByAvailable extends StandardLocaleHandler {
#Override
protected Locale getTrueLocale(HttpServletRequest req, HttpServletResponse resp, List<String> localeList, String defaultLocale, Integer cookieAge) {
if (isNull(req.getSession().getAttribute(LANG_ATTRIBUTE)) && isNull(req.getCookies())) {
return setAvailable(req, resp, localeList, defaultLocale, cookieAge);
}
return null;
}
}
public class GetLocaleBySession extends StandardLocaleHandler {
#Override
protected Locale getTrueLocale(HttpServletRequest req, HttpServletResponse resp, List<String> localeList, String defaultLocale, Integer cookieAge) {
if (nonNull(req.getSession().getAttribute(LANG_ATTRIBUTE))) {
LOG.debug(req.getParameter(LANG_ATTRIBUTE));
return new Locale((String) req.getSession().getAttribute(LANG_ATTRIBUTE));
}
return null;
}
}
I formed my chain of repsonsibility on this way:
public class ChainBuilder {
private List<StandardLocaleHandler> localeHandlers = new ArrayList<>();
public void addToFilterList(StandardLocaleHandler filter) {
if (!localeHandlers.contains(filter)) {
localeHandlers.add(filter);
} else {
throw new IllegalArgumentException("Already in the list");
}
}
public StandardLocaleHandler createChainOfResponsibility() {
for (int i = 0; i < localeHandlers.size() - 1; i++) {
localeHandlers.get(i).setNext(localeHandlers.get(i + 1));
}
return localeHandlers.get(0);
}
}
ChainBuilder builder = new ChainBuilder();
builder.addToFilterList(new GetLocaleByAvailable());
builder.addToFilterList(new GetLocaleByParam());
builder.addToFilterList(new GetLocaleBySession());
builder.addToFilterList(new GetLocaleByCookie());
StandardLocaleHandler handler = builder.createChainOfResponsibility();
return handler.getTrueLocale(req, resp, localeList, defaultLocale, cookieAge);
How can I go to the next item in the chain if it returns null?
public abstract class StandardLocaleHandler {
public final Locale getTrueLocale() {
Locale local = getTrueLocaleInternal();
return local == null && localeHandler != null ? localeHandler.getTrueLocale() : local;
}
protected abstract Locale getTrueLocaleInternal();
}
public class GetLocaleByAvailable extends StandardLocaleHandler {
#Override
protected Locale getTrueLocaleInternal() {
// TODO logic
return null;
}
}
You need to change code to something like this
public class GetLocaleByAvailable extends StandardLocaleHandler {
#Override
protected Locale getTrueLocale(HttpServletRequest req, HttpServletResponse resp, List<String> localeList, String defaultLocale, Integer cookieAge) {
Locale result = null;
if (isNull(req.getSession().getAttribute(LANG_ATTRIBUTE)) && isNull(req.getCookies())) {
result = setAvailable(req, resp, localeList, defaultLocale, cookieAge);
}
if (result == null) {
StandardLocaleHandler nextHandler = getNext();
if (nextHandler == null) {
return nextHandler.getTrueLocale(....);
}
}
return result;
}
}
And the same for another Handler class.

How to initialize Multipart request for custom HttpServeletRequest

I am using springboot 2x. Our project is using a Custom HttpServeletRequest which extends HttpServletRequestWrapper and implements MultipartHttpServletRequest. Everything works fine. But when I want to work for file upload, it can't initialized Multipart request. It shows error :
java.lang.IllegalStateException: Multipart request not initialized
My question is, how can I solve this error. How Multipart request will be initialized.
I am giving all code regarding this.
public class XHttpServletRequest extends HttpServletRequestWrapper implements MultipartHttpServletRequest {
public XHttpServletRequest (HttpServletRequest request) {
super(request);
}
private MultiValueMap<String, MultipartFile> multipartFiles;
private String method;
#Override
public String getMethod() {
if (this.method == null) return super.getMethod();
return this.method;
}
public void setMethod(String method) {
this.method = method;
}
private Map<String,String[]> parameters = new LinkedHashMap<String,String[]>();
public void setParameter(String name, String value) {
parameters.put(name, new String[] {value});
}
#Override
public String getParameter(String name) {
if (parameters.get(name) != null) {
return parameters.get(name)[0];
}
HttpServletRequest req = (HttpServletRequest) super.getRequest();
return req.getParameter(name);
}
public Map<String, String[]> getParameterMap() {
Map<String, String[]> result = new LinkedHashMap<String, String[]>();
result.putAll(super.getRequest().getParameterMap());
result.putAll(parameters);
return Collections.<String, String[]>unmodifiableMap(result);
}
public Enumeration<String> getParameterNames() {
Set<String> result = new LinkedHashSet<String>(Collections.list(super.getRequest().getAttributeNames()));
result.addAll(parameters.keySet());
return new Vector<String>(result).elements();
}
public String[] getParameterValues(String name) {
if (parameters.get(name) != null) {
return parameters.get(name);
}
HttpServletRequest req = (HttpServletRequest) super.getRequest();
return req.getParameterValues(name);
}
#Override
public HttpServletRequest getRequest() {
return (HttpServletRequest) super.getRequest();
}
#Override
public HttpMethod getRequestMethod() {
return HttpMethod.resolve(getRequest().getMethod());
}
#Override
public HttpHeaders getRequestHeaders() {
HttpHeaders headers = new HttpHeaders();
Enumeration<String> headerNames = getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
headers.put(headerName, Collections.list(getHeaders(headerName)));
}
return headers;
}
#Override
public HttpHeaders getMultipartHeaders(String s) {
return null;
}
#Override
public Iterator<String> getFileNames() {
return getMultipartFiles().keySet().iterator();
}
#Override
public MultipartFile getFile(String name) {
return getMultipartFiles().getFirst(name);
}
#Override
public List<MultipartFile> getFiles(String name) {
List<MultipartFile> multipartFiles = getMultipartFiles().get(name);
if (multipartFiles != null) {
return multipartFiles;
}
else {
return Collections.emptyList();
}
}
#Override
public Map<String, MultipartFile> getFileMap() {
return getMultipartFiles().toSingleValueMap();
}
#Override
public MultiValueMap<String, MultipartFile> getMultiFileMap() {
return getMultipartFiles();
}
#Override
public String getMultipartContentType(String s) {
return null;
}
/**
* Set a Map with parameter names as keys and list of MultipartFile objects as values.
* To be invoked by subclasses on initialization.
*/
protected final void setMultipartFiles(MultiValueMap<String, MultipartFile> multipartFiles) {
this.multipartFiles =
new LinkedMultiValueMap<>(Collections.unmodifiableMap(multipartFiles));
}
/**
* Obtain the MultipartFile Map for retrieval,
* lazily initializing it if necessary.
* #see #initializeMultipart()
*/
protected MultiValueMap<String, MultipartFile> getMultipartFiles() {
if (this.multipartFiles == null) {
initializeMultipart();
}
return this.multipartFiles;
}
/**
* Lazily initialize the multipart request, if possible.
* Only called if not already eagerly initialized.
*/
protected void initializeMultipart() {
throw new IllegalStateException("Multipart request not initialized");
}
}
Another class extends XHttpServletRequest and this is instead of HttpServeletRequest in our project. The following code:
public class YHttpRequest extends MutableHttpServletRequest {
private ByteArrayOutputStream cachedBytes;
public YHttpRequest(HttpServletRequest request) {
super(request);
}
#Override
public ServletInputStream getInputStream() throws IOException {
if (cachedBytes == null)
cacheInputStream();
return new CachedServletInputStream();
}
#Override
public BufferedReader getReader() throws IOException{
return new BufferedReader(new InputStreamReader(getInputStream()));
}
private void cacheInputStream() throws IOException {
/* Cache the inputstream in order to read it multiple times. For
* convenience, I use apache.commons IOUtils
*/
cachedBytes = new ByteArrayOutputStream();
IOUtils.copy(super.getInputStream(), cachedBytes);
}
public List<Map<String, Object>> getListData() throws RequestException {
List<Map<String, Object>> data = new ArrayList<>();
try {
ObjectMapper mapper = new ObjectMapper();
data = mapper.readValue(this.getInputStream(), new TypeReference<ArrayList<LinkedHashMap>>(){});
System.out.println(data);
}
catch (Exception e) {
// System.out.println(e.)
throw new RequestException("Unable to parse request data", e);
}
return data;
}
private Object cachedData = null;
public Object getRawData() throws RequestException {
Object data = new LinkedHashMap<>();
try {
ObjectMapper mapper = new ObjectMapper();
// data = mapper.readValue(this.getInputStream());
try {
data = mapper.readValue(this.getInputStream(), new TypeReference<HashMap>() {
});
}
catch (JsonMappingException e) {
// e.printStackTrace();
}
try {
data = mapper.readValue(this.getInputStream(), new TypeReference<List<HashMap>>() {
});
}
catch (JsonMappingException e) {
// e.printStackTrace();
}
System.out.println(data);
}
catch (Exception e) {
// System.out.println(e.)
throw new RequestException("Unable to parse request data", e);
}
return data;
}
public Object getData() throws RequestException {
if (this.cachedData == null) {
this.cachedData = this.getRawData();
}
return this.cachedData;
}
/* An inputstream which reads the cached request body */
public class CachedServletInputStream extends ServletInputStream {
private ByteArrayInputStream input;
public CachedServletInputStream() {
/* create a new input stream from the cached request body */
input = new ByteArrayInputStream(cachedBytes.toByteArray());
}
#Override
public boolean isFinished() {
return input.available() == 0;
}
#Override
public boolean isReady() {
return true;
}
#Override
public void setReadListener(ReadListener readListener) {
// throw new IOException("zubair says: Method not implemented in Cached Servlet Input Stream class");
}
#Override
public int read() throws IOException {
return input.read();
}
}
// Storage for Path variable
private Map<String, Object> pathVariableMap = null;
public Map<String, Object> getPathVariableMap() {
if (this.pathVariableMap == null) {
this.pathVariableMap = new LinkedHashMap<>();
this.pathVariableMap.putAll((Map<? extends String, ?>) this.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE));
}
return this.pathVariableMap;
}
public Object getPathVariable(String key) {
return this.getPathVariableMap().get(key);
}
public FurinaHttpRequest setPathVariable(String key, Object value) {
this.getPathVariableMap().put(key, value);
return this;
}
public FurinaHttpRequest clearPathVariableMap() {
this.getPathVariableMap().clear();
return this;
}
}
The controller code:
public String handleFileUpload(YHttpRequest request) {
if (request.getMethod().equalsIgnoreCase("GET")){
return "{}";
}
Map<String, MultipartFile> file= request.getFileMap();
try {
for(Map.Entry<String, MultipartFile> entry : file.entrySet()){
storageService.store(entry.getValue());
//model.addAttribute("message", "You successfully uploaded " + entry.getValue().getOriginalFilename() + "!");
files.add(entry.getValue().getOriginalFilename());
}
} catch (Exception e) {
//model.addAttribute("message", "FAIL to upload !");
}
return "{}";
}
This will work
public String handleFileUpload(YHttpRequest request) {
if (request.getMethod().equalsIgnoreCase("GET")){
return "{}";
}
StandardMultipartHttpServletRequest standardMultipartHttpServletRequest = new StandardMultipartHttpServletRequest(request);
Map<String, MultipartFile> file= request.getFileMap();
try {
for(Map.Entry<String, MultipartFile> entry : file.entrySet()){
storageService.store(entry.getValue());
//model.addAttribute("message", "You successfully uploaded " + entry.getValue().getOriginalFilename() + "!");
files.add(entry.getValue().getOriginalFilename());
}
} catch (Exception e) {
//model.addAttribute("message", "FAIL to upload !");
}
return "{}";
}

trying to change request in Filter, so that it reflect in #RequestParam

I am trying the read the request attributes and change them using Filter, so that in Controller I would receive changed values as per my need. but the changes I did in Filter is not reflected in #RequestParam.
My controller:
public Response getDetails(HttpServletRequest req, #RequestParam(required = false) String userId) {
System.out.println("attrib in request:"+req.getParameter("userId"));
System.out.println("attrib in RequestParam:"+userId);
}
My Filter:
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
try {
System.out.println("inside filter---------------------------");
HtmlRequestWrapper req = new HtmlRequestWrapper(request);
chain.doFilter(req, response);
} catch (Exception ex) {
request.setAttribute("errorMessage", ex);
// request.getRequestDispatcher("/WEB-INF/views/jsp/error.jsp").forward(request,
// response);
}
}
My HttpServletRequestWrapper(HtmlRequestWrapper):
public class HtmlRequestWrapper extends HttpServletRequestWrapper {
public HtmlRequestWrapper(ServletRequest request) {
super((HttpServletRequest) request);
}
public String sanitize(String input) {
String result = "";
result = input + "bla bla";
return result;
}
public String getParameter(String paramName) {
String value = super.getParameter(paramName);
value = sanitize(value);
return value;
}
public String[] getParameterValues() {
String values[] = null;
// String values[] = request.getParameterValues(paramName);
for (Enumeration<String> en = super.getParameterNames(); en.hasMoreElements();) {
String paramName = (String) en.nextElement();
values = super.getParameterValues(paramName);
int n = values.length;
for (int i = 0; i < n; i++) {
System.out.println("param val before: " + values[i]);
values[i] = sanitize(values[i]);
System.out.println("param val after: " + values[i]);
}
}
return values;
}
public Map<String, String[]> getParameterMap() {
Map<String, String[]> paramMap = new HashMap<>();
String values[] = null;
for (Enumeration<String> en = super.getParameterNames(); en.hasMoreElements();) {
String paramName = (String) en.nextElement();
values = super.getParameterValues(paramName);
int n = values.length;
for (int i = 0; i < n; i++) {
System.out.println("param val before in map: " + values[i]);
values[i] = sanitize(values[i]);
System.out.println("param val after in map: " + values[i]);
}
paramMap.put(paramName, values);
this.getRequest().setAttribute(paramName, values);
}
return Collections.unmodifiableMap(paramMap);
}
}
as you can see i am just trying to append some text to the attribute values.In real scenario would be cleaning and appending with some logic.
Note: In my controller I get the changed value in req.getParameter("userId") but #RequestParam(required = false) String userId contains the same old values passed down from the actual request.
I want #RequestParam(required = false) String userId to reflect the changes in req.getParameter("userId").
updating(Adding WebConfig class):
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new ServiceInterceptor());
}
#Bean
public Filter htmlFilter() {
return new HtmlFilter();
}

Redirect servlet async and heart beat

We have tasks in java web-app that take a long time in completing and before the time the task completes the request times out and page cannot be displayed happens. We are think of setting a async redirection servlet that acts as a front-controller redirecting the request to the appropriate action classes and while the request is being served the servlet keeps sending a heartbeat every minute or so, until the request is completed by the corresponding action classes. Has anybody implemented something similar using asynchronous servlet 3.0? Also is this possible? I understand that this is similar to server push. Thanks for guidance.
yes this kind of functionality you can achive by use of
asynchronous servlet 3.0.it basically works like push
notification and also give you respose continously with
out making request here i have one code that i share with
this code may help for you to make async request.
this example check live users
#WebServlet(urlPatterns = { "/checkliveuser" }, asyncSupported = true)
public class CheckLiveUser extends HttpServlet {
private static final long serialVersionUID = 1L;
private static final Queue<AsyncContext> queue = new ConcurrentLinkedQueue();
private static final BlockingQueue<String> messageQueue = new LinkedBlockingQueue();
private static final String BEGIN_SCRIPT_TAG = "<script type='text/javascript'>\n";
private static final String END_SCRIPT_TAG = "</script>\n";
private Thread notifierThread = null;
#Override
public void init(ServletConfig config) throws ServletException {
ServletContext context = config.getServletContext();
Set<String> users = new HashSet<String>();
Map<String, String> page = new HashMap<String, String>();
context.setAttribute("page", page);
context.setAttribute("messageQueue", messageQueue);
Runnable notifierRunnable = new Runnable() {
public void run() {
boolean done = false;
while (!done) {
System.out.println("in thread");
String cMessage = null;
try {
cMessage = BEGIN_SCRIPT_TAG + toJsonp("<b>Live User:", messageQueue.take())
+ END_SCRIPT_TAG;
for (AsyncContext ac : queue) {
try {
PrintWriter acWriter = ac.getResponse()
.getWriter();
acWriter.println(cMessage);
acWriter.flush();
} catch (IOException ex) {
System.out.println(ex);
queue.remove(ac);
}
}
} catch (InterruptedException iex) {
done = true;
System.out.println(iex);
}
}
}
};
notifierThread = new Thread(notifierRunnable);
notifierThread.start();
}
/**
* #see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter writer = response.getWriter();
request.setAttribute("org.apache.catalina.ASYNC_SUPPORTED", true);
final AsyncContext ac = request.startAsync();
ac.setTimeout(10 * 60 * 1000 * 1000);
ac.addListener(new AsyncListener() {
public void onComplete(AsyncEvent event) throws IOException {
queue.remove(ac);
System.out.println("on complete");
}
public void onTimeout(AsyncEvent event) throws IOException {
queue.remove(ac);
System.out.println("on timeout");
}
public void onError(AsyncEvent event) throws IOException {
queue.remove(ac);
System.out.println("on error");
}
public void onStartAsync(AsyncEvent event) throws IOException {
System.out.println("on startup");
}
});
queue.add(ac);
}
/**
* #see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/plain");
response.setCharacterEncoding("UTF-8");
ServletContext context = request.getServletContext();
HttpSession session = request.getSession();
Map<String, String> logins = (Map<String, String>) context
.getAttribute("page");
if (request.getParameter("action") != null
&& !request.getParameter("action").isEmpty()) {
if (request.getParameter("action").equalsIgnoreCase("logout")) {
logins.remove(request.getSession().getId());
request.getSession().invalidate();
}
}
String name = request.getParameter("loginID");
if (name != null) {
session.setAttribute("user", name);
session.setAttribute("jsessionId", session.getId());
logins.put(session.getId(), name);
}
String html = "";
for (Map.Entry<String, String> entry : logins.entrySet()) {
System.out.println("Key : " + entry.getKey() + " Value : "
+ entry.getValue());
html += entry.getValue() + "<br>";
}
String cMessage = BEGIN_SCRIPT_TAG + toJsonp("<b>Live User:", html)
+ END_SCRIPT_TAG;
notify(cMessage);
response.getWriter().println("success");
if (request.getParameter("action") != null
&& !request.getParameter("action").isEmpty()) {
if (request.getParameter("action").equalsIgnoreCase("logout"))
response.sendRedirect("login.jsp");
} else {
response.sendRedirect("welcome.jsp");
}
}
#Override
public void destroy() {
queue.clear();
notifierThread.interrupt();
}
private void notify(String cMessage) throws IOException {
try {
messageQueue.put(cMessage);
} catch (Exception ex) {
IOException t = new IOException();
t.initCause(ex);
throw t;
}
}
private String escape(String orig) {
StringBuffer buffer = new StringBuffer(orig.length());
for (int i = 0; i < orig.length(); i++) {
char c = orig.charAt(i);
switch (c) {
case '\b':
buffer.append("\\b");
break;
case '\f':
buffer.append("\\f");
break;
case '\n':
buffer.append("<br />");
break;
case '\r':
// ignore
break;
case '\t':
buffer.append("\\t");
break;
case '\'':
buffer.append("\\'");
break;
case '\"':
buffer.append("\\\"");
break;
case '\\':
buffer.append("\\\\");
break;
case '<':
buffer.append("<");
break;
case '>':
buffer.append(">");
break;
case '&':
buffer.append("&");
break;
default:
buffer.append(c);
}
}
return buffer.toString();
}
private String toJsonp(String name, String message) {
return "window.parent.app.update({ name: \"" + escape(name)
+ "\", message: \"" + escape(message) + "\" });\n";
}

How to write to a HttpServletResponse response object?

I have this action class, this class takes care of my response
Update now passing response from DownloadStatus class, but it looks like it is null
public final class DownloadStatus extends ActionSupport implements ServletRequestAware,ServletResponseAware
{
static Logger logger = Logger.getLogger(DownloadStatus.class);
private HttpServletRequest request;
private HttpServletResponse response;
private File cfile;
private String cfileFileName;
#Override
public String execute()
{
logger.debug("Inside DownloadStatus.execute method")
try {
ChainsInvoker invoker = new ChainsInvoker()
def executionResponse = invoker.invoke(request, MYChains.download, cfile, cfileFileName)
if(executionResponse == null || ErrorHandler.checkIfError(executionResponse))
{
return ERROR
}
response.setContentType("APPLICATION/xml")
logger.debug("filename: $cfileFileName")
response.addHeader("Content-Disposition", "attachment; filename=\""+cfileFileName+"\"")
response.getWriter().print(executionResponse)
logger.debug("executionResponse :" + executionResponse)
invoker.invoke(MYChains.clean)
}catch (Exception exp) {
logger.error("Exception while Creating Status ")
logger.error(exp.printStackTrace())
}
return NONE
}
#Override
public void setServletRequest(HttpServletRequest request) { this.request = request; }
#Override
public void setServletResponse(HttpServletResponse response) { this.response = response; }
public File getcfile() { cfile }
public void setcfile(File cfile) { this.cfile = cfile }
public String getcfileFileName() { cfileFileName }
public void setcfileFileName(String cfileFileName){ this.cfileFileName = cfileFileName }
}
and below class to write stream into response
class DownloadStatusResponse implements Command {
static Logger logger = Logger.getLogger(DownloadStatusResponse.class);
#Override
public boolean execute(Context ctx) throws Exception
{
logger.debug("Inside DownloadStatusResponse.execute() method")
OutputStream response = null;
if(ctx.get(ContextParams.absFileName) != null && ctx.get(ContextParams.absFileName).toString().trim().length() != 0 )
{
HttpServletResponse resp = ctx.get(ContextParams.response)
/*I am trying to get Response here*/
response=downloadStatusFile(ctx.get(ContextParams.absFileName).toString(),resp)
}
logger.debug("Response: " + response)
ctx.put(ContextParams.response,response); /*ContextParams is a enum of keywords, having response*/
return false;
}
private OutputStream downloadStatusFile(String filename,HttpServletResponse resp)
{
logger.info("Inside downloadStatusFile() method")
File fname = new File(filename)
if(!fname.exists())
{
logger.info("$filename does not exists")
return null
}
else
{
resp.setContentType("APPLICATION/xml")
/*Exception: cannot setContentType on null object*/
resp.addHeader("Content-Disposition", "attachment; filename=\""+fname.getName()+"\"")
FileInputStream istr = new FileInputStream(fname)
OutputStream ostr = resp.getOutputStream()
/*I need to use resp.getOutputStream() for ostr*/
int curByte=-1;
while( (curByte=istr.read()) !=-1)
ostr.write(curByte)
ostr.flush();
}
return ostr
}
}
My question is how can ostr be returned to the response in DownloadStatus class?
Update (working test servlet)
I have this below servlet which does the job of getting file content into a stream and giving it back to the HttpServletResponse, but i want to use it in above code
public class DownloadServlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String fileName = req.getParameter("zipFile");
if(fileName == null) return;
File fname = new File(fileName);
System.out.println("filename");
if(!fname.exists()) {System.out.println("Does not exists"); return;}
FileInputStream istr = null;
OutputStream ostr = null;
//resp.setContentType("application/x-download");
resp.setContentType("APPLICATION/ZIP");
resp.addHeader("Content-Disposition", "attachment; filename=\""+fname.getName()+"\"");
System.out.println(fname.getName());
try {
istr = new FileInputStream(fname);
ostr = resp.getOutputStream();
int curByte=-1;
while( (curByte=istr.read()) !=-1)
ostr.write(curByte);
ostr.flush();
} catch(Exception ex){
ex.printStackTrace(System.out);
} finally{
try {
if(istr!=null) istr.close();
if(ostr!=null) ostr.close();
} catch(Exception ex){
ex.printStackTrace();
System.out.println(ex.getMessage());
}
}
try {
resp.flushBuffer();
} catch(Exception ex){
ex.printStackTrace();
System.out.println(ex.getMessage());
}
}
}
As far as I understand all you require is how to download a file using Struts2.
You need something like this is your struts.xml file
<action name="downloadfile" class="DownloadAction">
<result name="success" type="stream">
<param name="contentType">application/pdf</param>
<param name="inputName">inputStream</param>
<param name="contentDisposition">attachment;filename="document.pdf"</param>
<param name="bufferSize">1024</param>
</result>
</action>
Code:
public class DownloadAction extends ActionSupport {
private InputStream inputStream;
public InputStream getInputStream() {
return inputStream;
}
public void setInputStream(InputStream inputStream) {
this.inputStream = inputStream;
}
public String execute() throws FileNotFoundException {
String filePath = ServletActionContext.getServletContext().getRealPath("/uploads");
File f = new File(filePath + "/nn.pdf");
System.out.println(f.exists());
inputStream = new FileInputStream(f);
return SUCCESS;
}
}

Categories