Time for action – creating a context Listener

We will now create and configure a Listener and a Servlet respectively inside our project. Finally, we will initiate our server and test the service by executing our report inside a web browser.

  1. To be able to function efficiently, PRD's API requires a process of initialization. This process will load libraries and perform tasks related to the setup of the execution environment needed to process reports rapidly. We can perform this initialization using a certain type of web components, called Listeners.

    Listeners are used to process events that are divided into categories and are generated by the server at various levels. In our case, we are interested in listening to events at a container level, particularly at the time at which the container is initiated. This is done so that the users do not have to pay the price of initializing components, thus improving the users' experience in a noticeable way.

  2. Next, we will create a Listener inside our project.

    We will head to the Project Explorer panel, select the node named prd5Ch14, right-click on it, and then go to New | Other.... In the following window, inside the Web category we will select the Listener item and then click on Next > so that we are presented with the corresponding wizard.

  3. On the first screen of the wizard, we will complete the fields with the following data:
    • Java package = com.prd.web.listeners
    • Class name = InitListener
  4. We will click on the Next > button to continue.
  5. On the following screen, we need to define the events that our component will be listening to. Inside the Servlet context event section, we will check the option Lifecycle.
  6. We will now click on the Finish button to continue.
  7. Once the component is created, we will automatically be presented with the Java editor. If we take a look at the Project Explorer panel, within the prd5Ch14 node present in the location Java Resources | src we will now find our newly created Listener as shown in the following screenshot:
    Time for action – creating a context Listener
  8. We should now delete all the code within InitListener.java and replace it with the following code:
    package com.prd.web.listeners;
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    import javax.servlet.annotation.WebListener;
    import org.pentaho.reporting.engine.classic.core.ClassicEngineBoot;
    
    @WebListener
    public class InitListener implements ServletContextListener {
    
        public void contextInitialized(ServletContextEvent event) {
          ClassicEngineBoot.getInstance().start();
        }
        
        public void contextDestroyed(ServletContextEvent event) {
        }
    }

    Note

    To indicate that this is a Listener, we are making use of the @WebListener annotation, which is found right before the definition of the class. The interfaces implemented by ServletContextListener define what types of events are being listened to. In our case, we are interested in executing the PRD engine initialization code every time the container is started; that is why we included the line ClassicEngineBoot.getInstance().start(); within the contextInitialized() method. We should now save the changes made to this file.

  9. Next we will be creating a Servlet. Servlets are the most appropriate components to handle petitions, perform processing, and execute routings, but are not well suited to execute presentation logic. As we will discuss later in this chapter, presentation logic will be left to PRD's API and a JSP.
  10. We will head to the Project Explorer panel, select the prd5Ch14 node, right-click on it, and then go to New | Other.... In the following window, inside the Web category we will select the Servlet item and click on Next > to be presented with the corresponding wizard.
  11. On the first screen in the wizard, we will complete the fields with the following data:
    • Java package = com.prd.web.actions
    • Class name = RunReport

    We will click on the Next > button to continue.

  12. In the following part of the wizard, we will define URL Mapping; this feature allows us to define which URL the client should request to have the Servlet execute its code.

    In the URL Mapping section, we will select the /RunReport item, click on the Edit... button, place the name /runReport, and then click on OK.

    Note

    As can be seen, all we had to do was change the first letter from upper to lowercase; this is done to honor good programming practices.

    We will now click on the Finish button to continue.

  13. Once the Servlet is created, we will automatically be presented with the Java editor. If we take a look at the Project Explorer panel, within the node named prd5Ch14 located in Java Resources | src we can now find our newly created Servlet as shown in the following screenshot:
    Time for action – creating a context Listener
  14. We will now delete all the code within RunReport.java and copy the following code. We should pay special attention to the comments (pieces of text within /* and */) placed throughout the code since they will help us understand it:
    /* Header: contains the package and necessary imports. */
    package com.prd.web.actions;
    
    import java.io.File;
    import java.io.IOException;
    import java.net.URL;
    import javax.servlet.RequestDispatcher;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import org.pentaho.reporting.engine.classic.core.MasterReport;
    import org.pentaho.reporting.engine.classic.core.ReportProcessingException;
    import org.pentaho.reporting.engine.classic.core.modules.output.pageable.pdf.PdfReportUtil;
    import org.pentaho.reporting.engine.classic.core.modules.output.table.base.StreamReportProcessor;
    import org.pentaho.reporting.engine.classic.core.modules.output.table.html.AllItemsHtmlPrinter;
    import org.pentaho.reporting.engine.classic.core.modules.output.table.html.FileSystemURLRewriter;
    import org.pentaho.reporting.engine.classic.core.modules.output.table.html.HtmlPrinter;
    import org.pentaho.reporting.engine.classic.core.modules.output.table.html.StreamHtmlOutputProcessor;
    import org.pentaho.reporting.libraries.repository.ContentIOException;
    import org.pentaho.reporting.libraries.repository.ContentLocation;
    import org.pentaho.reporting.libraries.repository.DefaultNameGenerator;
    import org.pentaho.reporting.libraries.repository.file.FileRepository;
    import org.pentaho.reporting.libraries.resourceloader.Resource;
    import org.pentaho.reporting.libraries.resourceloader.ResourceException;
    import org.pentaho.reporting.libraries.resourceloader.ResourceManager;
    
    /* The next line defines that this class is a Servlet, as well as the URL Mapping.  */
    @WebServlet("/runReport")
    public class RunReport extends HttpServlet {
    
      private static final long serialVersionUID = 1L;
    
      /* Method doGet(): this determines that this class will only respond to requests of the type HTTP GET. */
      protected void doGet(HttpServletRequest request,
                       HttpServletResponse response) throws ServletException, IOException {
    
       /* The following three lines take the parameters sent by the client and assign them to variables. In our case, we need "year" and "month" so that we can pass them to the PRD engine, since in our report we have defined the parameters "SelectYear"and "SelectMonth" respectively. The parameter "outputType" will 
    help us to determine which type of output was required by the user.*/
        Integer year = Integer.parseInt(request.getParameter("year"));
        Integer month = Integer.parseInt(request.getParameter("month"));
        String outputType = request.getParameter("outputType");
    
        String errorMsg = "";
        try {
    /* The call to doReport() is the one that will finally process the report.*/
          doReport(year, month, outputType, response);
        } catch (Exception e) {
          e.printStackTrace();
          errorMsg = "ERROR: " + e.getMessage();
        }
    /* The following if checks if an error has occurred, in which case creates a string with the error message and stores it in an attribute of the "request" object, and then performs a redirect to the index. */
        if (errorMsg.length() > 0) {
          request.setAttribute("errorMsg", errorMsg);
          RequestDispatcher dispatcher = getServletContext()
            .getRequestDispatcher("/index.jsp");
          dispatcher.forward(request, response);
        }
    }
    
      /* Method doReport(): */
      private void doReport(Integer year, Integer month, String type,
          HttpServletResponse response) throws ReportProcessingException,
          IOException, ResourceException, ContentIOException {
        
        /* -> Global Setup */
        ResourceManager manager = new ResourceManager();
        manager.registerDefaults();
        URL urlToReport = new URL("file:"
            + getServletContext().getRealPath(
                "WEB-INF/report/11_Adding_Charts.prpt"));
        Resource res = manager.createDirectly(urlToReport, MasterReport.class);
        MasterReport report = (MasterReport) res.getResource();
    
        report.getParameterValues().put("SelectYear", year);
        report.getParameterValues().put("SelectMonth", month);
        response.setHeader("Content-disposition", "filename=out." + type);
    
         /* -> Output Type: pdf & html */
        if (type.equalsIgnoreCase("pdf")) {
          response.setContentType("application/pdf");
          PdfReportUtil.createPDF(report, response.getOutputStream());
      }
    
        if (type.equalsIgnoreCase("html")) {
          response.setContentType("text/html");
          String fileName = "_out" + System.currentTimeMillis() + "." + type;
          File folderOut = new File(getServletContext().getRealPath(
              "/out/" + System.currentTimeMillis()));
    
          if (!folderOut.exists()) {
            folderOut.mkdirs();
            final FileRepository targetRepository = new FileRepository(
                folderOut);
            final ContentLocation targetRoot = targetRepository.getRoot();
            final HtmlPrinter printer = new AllItemsHtmlPrinter(
                report.getResourceManager());
            printer.setContentWriter(targetRoot, new DefaultNameGenerator(
                targetRoot, fileName));
            printer.setDataWriter(targetRoot, new DefaultNameGenerator(
                targetRoot, "content"));
            printer.setUrlRewriter(new FileSystemURLRewriter());
            final StreamHtmlOutputProcessor outputProcessor = new StreamHtmlOutputProcessor(
                report.getConfiguration());
            outputProcessor.setPrinter(printer);
            final StreamReportProcessor reportProcessor = new StreamReportProcessor(
                report, outputProcessor);
            reportProcessor.processReport();
            reportProcessor.close();
    
            String route = "out/" + folderOut.getName() + "/" + fileName;
            response.sendRedirect(route);
          }
        }
      }
    }

    We will now save the changes to this file.

  15. So far we have created the components that are to be executed at the server side and that comprise the service itself. Next, we will test the service by executing our report in a web browser:
    1. We will head to the Server tab (bottom part of the UI), select our Tomcat v7.0 Server at localhost server, and start (or restart) it using the Time for action – creating a context Listener button.
    2. Once the Server is started, we will open a web browser and direct it to the following URL:
    3. http://localhost:8080/prdweb/runReport?year=2005&month=6&outputType=html

    The parameters we have sent are as follows:

    • year=2005
    • month=6
    • outputType=html
    Time for action – creating a context Listener

    We can keep testing by changing the values of the Parameters in the URL; for example, it would be interesting to see what the output of the report is if we placed outputType=pdf in the URL.

What just happened?

We created a Listener inside our project so that it performs the PRD's API initialization; we configured it and modified the code within the file named InitListener.java. We also created a Servlet inside our project so that it manages requests, processing, and routings; we configured it and modified the code within the file named RunReport.java. Finally, we started our server (Apache v7.0 Server at localhost) and tested the service by opening the following URL inside a web browser: http://localhost:8080/prdweb/runReport?year=2005&month=6&outputType=html.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset