-1

What I want:

If someone visits the page, could select two dates and click a (single) button for downloading the data between the two dates selected.

What I already have working:

JSP/web development is new for me. This is my scenario, using datepicker and JSP have a page that make a query to the database, return certain data between two dates, and create a .txt file with this data which saves locally.

Once the file is created, another button can be pressed to download the file.

What I need to work:

I need only one button who made both actions, so once the file is saved locally, a prompt for download appear and the visitor could make the download.

Because of how common the words are, it's hard to find what I need on search engines.

I need a button. I don't want links or anchors that looks like a button, this could be an easy matter for some folks, but I already have lost two days in

Info:

Apache Tomcat: 8.0.27 && Netbeans 8.1 && Ubuntu 14.04

JSP:

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags"%>
<%@taglib prefix="sj" uri="/struts-jquery-tags"%>

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <link rel="stylesheet" href="resources/css/jtable.css" type="text/css">        
        <link rel="stylesheet" href="resources/css/style.css" type="text/css">
        <link rel="stylesheet" href="resources/css/jquery-ui-1.10.3.custom.css" type="text/css">
        <link href="resources/css/jquery-ui-1.10.3.custom.css" rel="stylesheet" type="text/css" /> 
        <script src="resources/js/jquery-1.11.3.js" type="text/javascript"></script>
        <script src="resources/js/jquery-ui-1.10.3.custom.js" type="text/javascript"></script>
        <script src="resources/js/recuperacion-datos.js" type="text/javascript"></script>
        
        <title></title>
        <script>
            $(document).ready(function(){
                $("#datepicker1").datepicker({
                    maxDate: 0
                });
                $("#datepicker2").datepicker({ 
                    maxDate: 0,
                    onSelect: function(selected) {
                       $("#datepicker1").datepicker("option","maxDate", selected);
                    }
                });
            });
        </script>
    </head>
    <body>
    <center>
        <div class="jtable-main-container" style="width: 60%;">
            <div class="jtable-title">
            <div class="jtable-title-text">
                Recuperaci&oacute;n de Datos
            </div>
        </div>
            <div id="LecturasTableContainer" style="position: relative; text-align: center; font-size: 17px; top: 10px;">
           
                Fecha Inicio: <input type="text" name="fechaInicio" id="datepicker1"> <span>&nbsp;</span><span>&nbsp;</span>
                Fecha Fin: <input type="text" name="fechaFin" id="datepicker2">
                
                <!-- Button who generate the file -->
                
                <button type="submit" id="LoadRecordsButton" onclick="return confirm('Datos Recuperados');">Generar</button>
            </div>
                <br>  
                
                <!-- Button who download the file -->
                
                <s:form action="download" method="POST">
                    <s:submit value="Descargar" type="button"/>
                </s:form>                                    
        </div>
    
    </center>
    </body>
</html>

Action class for "Generar" Button:

package com.raspberry.struts.action;

import static com.opensymphony.xwork2.Action.SUCCESS;
import com.opensymphony.xwork2.ActionSupport;
import com.raspberry.dao.control.DBControl;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.apache.struts2.interceptor.ServletRequestAware;
import java.sql.Connection;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;

public class DataRecovery extends ActionSupport implements ServletRequestAware {
    
    public HttpSession session;
    public Connection c;
    public String fechaFin;// = null;
    public String fechaInicio; // = null;
    
    public String goDataRecovery(){
        session.setAttribute("mainopt", "dataRecovery");
        return SUCCESS;
    }
    
    public String doDataRecovery() throws ParseException, FileNotFoundException{  
        DBControl dato = new DBControl();
        
        fechaInicio = getFechaInicio();
        fechaFin = getFechaFin();      
        
        DateFormat df = new SimpleDateFormat("yyyMMMddkkmm");            
        String fecha = df.format(Calendar.getInstance().getTime());
              
        String lectura = dato.selecAlltLecturasFecha(fechaInicio, fechaFin);
        
        File archivo = new File ("/media/recovery"+fecha+".txt");
        archivo.getParentFile().mkdirs();
        PrintWriter printWriter;
        
        printWriter = new PrintWriter(archivo);
        printWriter.println (lectura);
        printWriter.close ();    

        return SUCCESS;        
    }
    
    public String getFechaFin() {        
        return fechaFin;
    }
    
    public String getFechaInicio() {
        return fechaInicio;
    }
    
    @Override
    public void setServletRequest(HttpServletRequest hsr) {
        session = hsr.getSession();
    }
}

Action Class for "Descargar" Button:

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import com.opensymphony.xwork2.ActionSupport;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;

public class DownloadAction extends ActionSupport{

    private InputStream fileInputStream;      

    public InputStream getFileInputStream() throws Exception {           
            return fileInputStream;
    }

    public String execute() throws Exception {
            
            DateFormat df = new SimpleDateFormat("yyyMMMddkkmm");            
            String fecha = df.format(Calendar.getInstance().getTime());
            
            fileInputStream = new FileInputStream(new File ("/media/recovery"+fecha+".txt"));
            
        return SUCCESS;
    }
}

Struts.xml:

<action name="GetDataRecovery" class="com.raspberry.struts.action.DataRecovery" 
        method="doDataRecovery">
    <interceptor-ref name="SessionValidationStack" />
    <result name="success">main.jsp</result>
    <result name="sessionexpired">index.jsp</result>            
</action>

<action name="download" class="com.raspberry.struts.action.DownloadAction">
    <result name="success" type="stream">
      <param name="contentType">application/octet-stream</param>
      <param name="inputName">fileInputStream</param>
      <param name="contentDisposition">attachment;filename="recovery.txt"</param>
      <param name="bufferSize">1024</param>
    </result>
</action>
Roman C
  • 49,761
  • 33
  • 66
  • 176
Elber CM
  • 310
  • 5
  • 21
  • create a form. Here is the reference: http://stackoverflow.com/questions/9549117/using-jsp-with-buttons – logger Jan 14 '16 at 22:15
  • @user3659052 thanks for your comment, my button already works for creating the .txt file locally. So your reference is helpfull but that part is ready. – Elber CM Jan 15 '16 at 13:23
  • @BalusC I don't think this is a duplicate. As you can see in the code, my JSP page already calls a servlet for creating the .txt file, so I Quote: "Several answers use links, I need a button" "I don't want an anchor that looks like a button" Please remove Duplicate Tag, because people who really can help me, could avoid this question. – Elber CM Jan 15 '16 at 13:28
  • Duplicate tells to use a form whose action URL points to servlet. – BalusC Jan 15 '16 at 13:29
  • @BalusC thanks for your comment. Maybe is because english is not my native language, but I think you're missing the point of my answer. So already improved my answer, and fix my code. Hopefully now is more clear what have already working, and what I need to work. ( Don't want to be rude, but once again, **please remove the duplicate**, that question is REALLY different from mine) – Elber CM Jan 15 '16 at 14:36
  • After your edit, your button still doesn't invoke any servlet via a form as demonstrated in the duplicate. Once you add a form which invokes the servlet, you can just write the file to response the usual way, exactly the same way as those examples with links which you apparently already found. – BalusC Jan 15 '16 at 16:00
  • 2
    The class you say Servlet is not a Servlet (the last code snippet). It is a Struts action class (`Action`, `ActionSupport` and `ServletRequestAware` are components of the Struts framework). – Tiny Jan 16 '16 at 19:42
  • 1
    To download you need another action that is mapped to another method that will do a download. Read [this](http://stackoverflow.com/a/18165136/573032) answer. – Roman C Jan 17 '16 at 10:31
  • @BalusC my bad, I was confused. What I need to do, could be made using ActionSupport, not servlets. Thanks for removing the duplicate tag. – Elber CM Jan 18 '16 at 15:07
  • @Tiny Thanks for your comment, you're right. I was confused. – Elber CM Jan 18 '16 at 15:07
  • @RomanC Thanks for your comment, you're right. I Already have the other class who made the download. I was following the Mykong example from the beginning, but was confused with servles, struts 1 and 2. Also thanks for the edition in my answer. – Elber CM Jan 18 '16 at 15:10
  • 1
    @ElberCM S1 and S2 are different frameworks built over servlets technology. – Roman C Jan 18 '16 at 18:48

2 Answers2

0

If you have followed the example, you should see that he was using two actions. One action is mapped to the JSP page, and another is used to download. First one is used to return an actionless result (class attribute is missing). It's needed to access JSP page through the action. If you follow this technique - first action, second JSP, then you can use Struts2.

You can also share the same JSP among different actions that return this JSP as a result. If you want to share the same JSP for two or more actions you should add a result that contains the name/path to the file.

You can use action class properties (not for actionless results) to hold the state of the action scope objects accessible in JSP via OGNL/JSTL or JSP EL.

Elements of type "submit" you should use inside the form, otherwise use type "button" and use javascript to submit the form (it doesn't concern s:submit tag though).

in the DataRecovery action class you should create a property for download link or some boolean to indicate that download is ready. Just keep the name of the action "download". If the property has a value then display the button for download.

<s:if test="downloadReady">
    <s:form action="download" method="POST">
        <s:submit type="button" cssClass="btn btn-primary" value="Descargar" />
    </s:form>                 
</s:if>

private boolean isDownloadReady = false;
//getters and setters

and set this variable after saving a file.

Roman C
  • 49,761
  • 33
  • 66
  • 176
0

First of all, thanks to @user3659052 @BalusC @Tiny and @Roman C , for your comments. All were very helpfull.

I was very confused, so after the comments enlightenment, decide to first start with some tutorials and yesterday get the web app working.

After fixing the struts action for the "Download Button", I tried to generate the file also in the Descargar Action Class, but the query to database was null.

The mistake was the form ID on the datepicker was pointing Generar Action Class, so the Descargar Action Class never get the data. So after change the pointer to the "correct" action, was able to get the dates, create the file (locally) and downloading in one action. (So Generar Action Class was deleted)

Struts .xml (fragment)

<action name="DataRecovery" class="com.raspberry.struts.action.DownloadAction" method="goDataRecovery">
    <interceptor-ref name="SessionValidationStack" />
    <result name="success">main.jsp</result>
    <result name="sessionexpired">index.jsp</result>            
</action>

<action name="GetRecovery" class="com.raspberry.struts.action.DownloadAction">
    <result name="success" type="stream">
      <param name="contentType">application/octet-stream</param>
      <param name="inputName">fileInputStream</param>
      <param name="contentDisposition">attachment;filename="recovery.txt"</param>
      <param name="bufferSize">1024</param>
    </result>
</action>  

Descargar Action Class

package com.raspberry.struts.action;

import static com.opensymphony.xwork2.Action.SUCCESS;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import com.opensymphony.xwork2.ActionSupport;
import com.raspberry.dao.control.DBControl;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.apache.struts2.interceptor.ServletRequestAware;

public class DownloadAction extends ActionSupport implements ServletRequestAware {

    public InputStream fileInputStream;
        public HttpSession session;
        public Connection c;
        public String fechaFin;// = null;
        public String fechaInicio; // = null;

        public String goDataRecovery(){
            session.setAttribute("mainopt", "dataRecovery");
            return SUCCESS;
        }

    public InputStream getFileInputStream() throws Exception {           
            return fileInputStream;
    }

        public String doDataRecovery() throws ParseException, FileNotFoundException{
            DBControl dato = new DBControl();

            fechaInicio = getFechaInicio();
            fechaFin = getFechaFin();

            DateFormat df = new SimpleDateFormat("yyyMMMddkkmm");            
            String fecha = df.format(Calendar.getInstance().getTime());

            String lectura = dato.selecAlltLecturasFecha(fechaInicio, fechaFin);

            File archivo = new File ("/media/recovery"+fecha+".txt");
            archivo.getParentFile().mkdirs();
            PrintWriter printWriter;

            printWriter = new PrintWriter(archivo);
            printWriter.println (lectura);
            printWriter.close();

            return SUCCESS;        
        }

        public String getFechaFin() {        
            return fechaFin;
        }

        public String getFechaInicio() {
            return fechaInicio;
        }

    public String execute() throws Exception {

            doDataRecovery();

            DateFormat df = new SimpleDateFormat("yyyMMMddkkmm");            
            String fecha = df.format(Calendar.getInstance().getTime());

            fileInputStream = new FileInputStream(new File ("/media/recovery"+fecha+".txt"));

        return SUCCESS;
    }

        @Override
        public void setServletRequest(HttpServletRequest hsr) {
            session = hsr.getSession();
        }
}

JSP

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags"%>
<%@taglib prefix="sj" uri="/struts-jquery-tags"%>

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <link rel="stylesheet" href="resources/css/jtable.css" type="text/css">        
        <link rel="stylesheet" href="resources/css/style.css" type="text/css">
        <link rel="stylesheet" href="resources/css/jquery-ui-1.10.3.custom.css" type="text/css">
        <link href="resources/css/jquery-ui-1.10.3.custom.css" rel="stylesheet" type="text/css" /> 
        <script src="resources/js/jquery-1.11.3.js" type="text/javascript"></script>
        <script src="resources/js/jquery-ui-1.10.3.custom.js" type="text/javascript"></script>
        <script src="resources/js/recuperacion-datos.js" type="text/javascript"></script>        
        <title></title>
        <script>
            $(document).ready(function(){
                $("#datepicker1").datepicker({
                    maxDate: 0
                });
                $("#datepicker2").datepicker({ 
                    maxDate: 0,
                    onSelect: function(selected) {
                       $("#datepicker1").datepicker("option","maxDate", selected);
                    }
                });
            });
        </script>       
    </head>
    <body>
    <center>
        <div class="jtable-main-container" style="width: 60%;">
            <div class="jtable-title">
                <div class="jtable-title-text">
                    Recuperaci&oacute;n de Datos
                </div>
            </div>
            <div style="position: relative; text-align: center; font-size: 17px; top: 10px;">
                <s:form theme="simple" action="GetRecovery" method="POST" id="LecturasTableContainer">          
                    Fecha Inicio: <input type="text" name="fechaInicio" id="datepicker1">
                    <span>&nbsp;</span><span>&nbsp;</span>
                    Fecha Fin: <input type="text" name="fechaFin" id="datepicker2">
                    <s:submit value="Descargar" id="LoadRecordsButton" type="button"/>
                </s:form>
            </div>
        </div>      
    </center>
    </body>
</html>

Once again thanks for the help.

Elber CM
  • 310
  • 5
  • 21