Monday, August 31, 2015

jQuery: Get the checked input checkbox elements

DOM Traversal and Selection

Get the checked <input> checkbox elements with the name "RIid" that are in the table with id "invoiceTable"

var invCheckboxesChecked = $('#invoiceTable input[name="RIid"]:checked');

Tuesday, June 30, 2015

Fix for undefined Javascript indexOf() function in IE 8

I suggest you use JQuery to address cross-browser compatibility issues like the support for the indexOf() function of an Array.

Put the code below at the top of your javascript file, after $(document).ready(function() {....}).

//if browser does not support Array.indexOf() method (IE8 and IE9) 
//use jQuery.inArray() method instead 
if (!Array.prototype.indexOf) {
    Array.prototype.indexOf = function(val) {
        return jQuery.inArray(val, this);
    };
}

This works perfect if you want to keep using the indexOf() function. This code provides a fallback for your site visitors who are using IE 8 and older browsers that does not support the Javascript indexOf() function for Array.

Saturday, May 30, 2015

Example of jQuery Ajax with JSON Payload in Request and JSON Response from Servlet

Here is an example of an ajax implementation using jQuery ajax with JSON payload and a servlet  using a JSON response.

Here's what you will need in your project:

Files under Web App Libraries:
jackson-annotations-2.4.0.jar
jackson-core--2.4.2.jar
jackson-databind-2.4.2.jar

File under \WebContent\js:
jquery-1.11.1.min.js


In your web.xml
 <servlet>
  <description>
  </description>
  <display-name>IncentiveClaimAjaxServlet</display-name>
  <servlet-name>IncentiveClaimAjaxServlet</servlet-name>
  <servlet-class>com.web.servlet.IncentiveClaimAjaxServlet</servlet-class>
 </servlet> 
 
 <servlet-mapping>
  <servlet-name>IncentiveClaimAjaxServlet</servlet-name>
  <url-pattern>/IncentiveClaimAjaxServlet</url-pattern>
 </servlet-mapping> 


In external javascript (IncentiveClearinghouse.js):
function submitComment(incentiveClaim, btnElement) {
 var newComment = $("#comment-input").val();  
 
 $("#comment-input").val(""); //clear the comment textarea
 $("#dialog-form").dialog( "close" ); //close the dialog

 
 incentiveClaim.approverComments = newComment;
 //alert(JSON.stringify({incentiveClaimJSONDTO: incentiveClaim}));

    $.ajax({
        type: "POST",
        url: "/IncentiveClearinghouseWeb/IncentiveClaimAjaxServlet?queueName=" + gQueueName + "&division=" + gDivision + "&user=" + gUser,
        //For the Jackson ObjectMapper to work on the server side - the KEY you assign to the JSON object (e.g. 'incentiveClaimJSONDTO') 
        //should be the same name as the property of the Java object it will map to (e.g. 'IncentiveClaimJSONWrapper.incentiveClaimJSONDTO) 
        data: JSON.stringify({incentiveClaimJSONDTO: incentiveClaim}),  
        contentType: "application/json; charset=UTF-8",
        dataType: "json",        
        success: function(response){
         var message = response[0].message;
         if (response[0].type == "S" && incentiveClaim.claimStatus != "U") {
          //if SAP response is success and status is Approve or Reject then update the admin comments in the DOM
          updateAdminComment(newComment, btnElement);
          //and replace buttons with the response success message
          showRespMsg(message, btnElement);
         } else if (response[0].type == "S" && incentiveClaim.claimStatus == "U") {
          //if SAP response is success and status is Update then update the admin comments in the DOM
          updateAdminComment(newComment, btnElement);
         } else if (response[0].type == "E") {
          //if SAP response is error then alert the response error message
          alert('Error: \n' + message);
         }
        },
        error: function(e){
            alert('Error: \n' + e);
        }
    });  
}


In jsp (ICHClaimList.jsp):
 <td class="<c:out value="${tdClass}" />">
  <button id="approveBtn" onclick="approve('${incentiveClaimDTO.dealerId}', '${incentiveClaimDTO.incentiveType}', '${incentiveClaimDTO.invoiceNumber}', '${incentiveClaimDTO.lineNbr}', '${incentiveClaimDTO.model}', '${incentiveClaimDTO.serialNumber}', '${incentiveClaimDTO.programId}', this);">Approve</button>         
  <button id="rejectBtn"  onclick="reject('${incentiveClaimDTO.dealerId}', '${incentiveClaimDTO.incentiveType}', '${incentiveClaimDTO.invoiceNumber}', '${incentiveClaimDTO.lineNbr}', '${incentiveClaimDTO.model}', '${incentiveClaimDTO.serialNumber}', '${incentiveClaimDTO.programId}', this);">Reject</button>
  <button id="updateBtn"  onclick="update('${incentiveClaimDTO.dealerId}', '${incentiveClaimDTO.incentiveType}', '${incentiveClaimDTO.invoiceNumber}', '${incentiveClaimDTO.lineNbr}', '${incentiveClaimDTO.model}', '${incentiveClaimDTO.serialNumber}', '${incentiveClaimDTO.programId}', this);">Update</button>         
 </td>



In servlet (IncentiveClaimAjaxServlet.java):
public class IncentiveClaimAjaxServlet extends HttpServlet   {

 private static final long serialVersionUID = 1L;
 private final LogHelper LOG = new LogHelper(this.getClass());
 
 private String user;
 
 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  String method = "doPost()";
  LOG.debug(method, "START");  

  String queueName = request.getParameter("queueName");
  String division = request.getParameter("division");
  user = request.getParameter("user");  
  try {
   ArrayList<IncentiveClaimResponseDTO> responseList = executeTask(request);
   
   //set response type to JSON
   response.setContentType("application/json");
   response.setHeader("cache-control", "no-cache");
         //initiate jackson mapper
   ObjectMapper mapper = new ObjectMapper();
   //send the JSON response to client
   mapper.writeValue(response.getOutputStream(), responseList);
   
  } catch(Exception ex) {
   ex.printStackTrace();
   LOG.error("Exception Processing AJAX Request: " + ex.getMessage());
   throw new ServletException(ex);
  }
 }
 
 public ArrayList<IncentiveClaimResponseDTO> executeTask(HttpServletRequest request) throws IOException, ServletException {

  //get received JSON data from request
  String jsonString = "";
  try {
   jsonString = getBody(request);
  } catch (IOException ex) {
   LOG.debug("Error in retrieving the JSON payload from the request"); 
  }
  LOG.debug("--------------------------------------");
  LOG.debug("JSON: \n" + jsonString); 
     
        //initiate jackson mapper
  ObjectMapper mapper = new ObjectMapper();
  IncentiveClaimJSONWrapper incentiveClaimJSONWrapper = new IncentiveClaimJSONWrapper();
  
  IncentiveClaimService claimService = IncentiveClaimService.getInstance();
  ArrayList<IncentiveClaimResponseDTO> responseList = new ArrayList<IncentiveClaimResponseDTO>();
  try {
   //convert JSON object to java object
   incentiveClaimJSONWrapper = mapper.readValue(jsonString, IncentiveClaimJSONWrapper.class);
   IncentiveClaimJSONDTO incentiveClaimJSONDTO = incentiveClaimJSONWrapper.getIncentiveClaimJSONDTO();
   
   responseList = claimService.processIncentive(mapJsonDTOToRequest(incentiveClaimJSONDTO)); 
   
  } catch (IncentiveClearinghouseException icex) {
   //errors.add(Constants.ERROR_MSG_CONSTANTS.ACTION_PROCESSING_ERROR, new ActionMessage("errors.decision.action", "Error Code: " + icex.getErrorCode(), "Exception: " + icex.getMessage()));
   LOG.error("IncentiveDecisionAction Error: " + icex.getMessage());
   icex.printStackTrace();
  } catch (Exception ex) {   
   //errors.add(Constants.ERROR_MSG_CONSTANTS.ACTION_PROCESSING_ERROR, new ActionMessage("errors.decision.action", "Error Code: " + Constants.EXCEPTION_CONSTANTS.ACTION_EXCEPTION, "Exception: " + ex.getMessage()));
   LOG.error("IncentiveDecisionAction Error: " + ex.getMessage());
   ex.printStackTrace();
  }
  
  return responseList;

 }
 
 public String getBody(HttpServletRequest request) throws IOException {
  BufferedReader br = null;
        String json = "";
  try {
         br = request.getReader();
         if(br != null){
             json = br.readLine();
         }    
     } catch (IOException ex) {
         throw ex;
     } finally {
         if (br != null) {
             try {
              br.close();
             } catch (IOException ex) {
                 throw ex;
             }
         }
     }
  return json;
 } 
 
 
 private IncentiveClaimDTO mapJsonDTOToRequest(IncentiveClaimJSONDTO incentiveClaimJSONDTO) throws IncentiveClearinghouseException {
  IncentiveClaimDTO claimDTO = new IncentiveClaimDTO();
  
  try {   
   claimDTO.setApproverComments(incentiveClaimJSONDTO.getApproverComments());
   if( incentiveClaimJSONDTO.getDealerId() != null && !incentiveClaimJSONDTO.getDealerId().equals("") )
    claimDTO.setDealerId(Integer.parseInt(incentiveClaimJSONDTO.getDealerId()));
   claimDTO.setClaimStatus(incentiveClaimJSONDTO.getClaimStatus());
   claimDTO.setIncentiveType(incentiveClaimJSONDTO.getIncentiveType());
   claimDTO.setInvoiceNumber(incentiveClaimJSONDTO.getInvoiceNumber());
   claimDTO.setLineNbr(incentiveClaimJSONDTO.getLineNumber());
   claimDTO.setModel(incentiveClaimJSONDTO.getModel());
   claimDTO.setModUserId(user);
   claimDTO.setProgramId(incentiveClaimJSONDTO.getProgramId());
   claimDTO.setSerialNumber(incentiveClaimJSONDTO.getSerialNumber());
  } catch (Exception ex) {
   throw new IncentiveClearinghouseException(Constants.EXCEPTION_CONSTANTS.ACTION_EXCEPTION, "Exception Mapping FormBean to Request");
  }
  
  return claimDTO;
 }
 
}


The DTOs:

IncentiveClaimResponseDTO
public class IncentiveClaimResponseDTO {

    private String field;
    private String id;
    private String logMsgNo;
    private String logNo;
    private String message;
    private String messageV1;
    private String messageV2;
    private String messageV3;
    private String messageV4;
    private String number;
    private String parameter;
    private BigInteger row;
    private String system;
    private String type; 
 
 public IncentiveClaimResponseDTO() {
  
 }

  

 public String getField() {
  return field;
 }


 public String getId() {
  return id;
 }


 public String getLogMsgNo() {
  return logMsgNo;
 }


 public String getLogNo() {
  return logNo;
 }


 public String getMessage() {
  return message;
 }


 public String getMessageV1() {
  return messageV1;
 }


 public String getMessageV2() {
  return messageV2;
 }


 public String getMessageV3() {
  return messageV3;
 }


 public String getMessageV4() {
  return messageV4;
 }


 public String getNumber() {
  return number;
 }


 public String getParameter() {
  return parameter;
 }


 public BigInteger getRow() {
  return row;
 }


 public String getSystem() {
  return system;
 }


 public String getType() {
  return type;
 }


 public void setField(String field) {
  this.field = field;
 }


 public void setId(String id) {
  this.id = id;
 }


 public void setLogMsgNo(String logMsgNo) {
  this.logMsgNo = logMsgNo;
 }


 public void setLogNo(String logNo) {
  this.logNo = logNo;
 }


 public void setMessage(String message) {
  this.message = message;
 }


 public void setMessageV1(String messageV1) {
  this.messageV1 = messageV1;
 }


 public void setMessageV2(String messageV2) {
  this.messageV2 = messageV2;
 }


 public void setMessageV3(String messageV3) {
  this.messageV3 = messageV3;
 }


 public void setMessageV4(String messageV4) {
  this.messageV4 = messageV4;
 }


 public void setNumber(String number) {
  this.number = number;
 }


 public void setParameter(String parameter) {
  this.parameter = parameter;
 }


 public void setRow(BigInteger row) {
  this.row = row;
 }


 public void setSystem(String system) {
  this.system = system;
 }


 public void setType(String type) {
  this.type = type;
 }



 @Override
 public String toString() {
  return getClass().getName() + " {\n\tfield: " + field + "\n\tid: " + id
    + "\n\tlogMsgNo: " + logMsgNo + "\n\tlogNo: " + logNo
    + "\n\tmessage: " + message + "\n\tmessageV1: " + messageV1
    + "\n\tmessageV2: " + messageV2 + "\n\tmessageV3: " + messageV3
    + "\n\tmessageV4: " + messageV4 + "\n\tnumber: " + number
    + "\n\tparameter: " + parameter + "\n\trow: " + row
    + "\n\tsystem: " + system + "\n\ttype: " + type + "\n}";
 }
}


IncentiveClaimJSONWrapper
public class IncentiveClaimJSONWrapper implements Serializable {

 private static final long serialVersionUID = 4804830588834912345L;

 private IncentiveClaimJSONDTO incentiveClaimJSONDTO;

 
 
 public IncentiveClaimJSONDTO getIncentiveClaimJSONDTO() {
  return incentiveClaimJSONDTO;
 }

 public void setIncentiveClaimJSONDTO(IncentiveClaimJSONDTO incentiveClaimJSONDTO) {
  this.incentiveClaimJSONDTO = incentiveClaimJSONDTO;
 }
 
 
}


IncentiveClaimJSONDTO
public class IncentiveClaimJSONDTO implements Serializable {

 private static final long serialVersionUID = 8439021168470172893L;
 
 private String claimStatus;
 private String dealerId;
 private String incentiveType;
 private String invoiceNumber;
 private String lineNumber;
 private String model;
 private String serialNumber;
 private String programId;
 private String approverComments;
 
 
 public String getClaimStatus() {
  return claimStatus;
 }
 public void setClaimStatus(String claimStatus) {
  this.claimStatus = claimStatus;
 }
 public String getDealerId() {
  return dealerId;
 }
 public void setDealerId(String dealerId) {
  this.dealerId = dealerId;
 }
 public String getIncentiveType() {
  return incentiveType;
 }
 public void setIncentiveType(String incentiveType) {
  this.incentiveType = incentiveType;
 }
 public String getInvoiceNumber() {
  return invoiceNumber;
 }
 public void setInvoiceNumber(String invoiceNumber) {
  this.invoiceNumber = invoiceNumber;
 }
 public String getLineNumber() {
  return lineNumber;
 }
 public void setLineNumber(String lineNumber) {
  this.lineNumber = lineNumber;
 }
 public String getModel() {
  return model;
 }
 public void setModel(String model) {
  this.model = model;
 }
 public String getSerialNumber() {
  return serialNumber;
 }
 public void setSerialNumber(String serialNumber) {
  this.serialNumber = serialNumber;
 }
 public String getProgramId() {
  return programId;
 }
 public void setProgramId(String programId) {
  this.programId = programId;
 }
 public String getApproverComments() {
  return approverComments;
 }
 public void setApproverComments(String approverComments) {
  this.approverComments = approverComments;
 }
 
 
}


That's it.

Thursday, April 30, 2015

Ajax and Struts 1 using jQuery Ajax with URL parameters

Here is an example of an ajax implementation using jQuery ajax with URL parameters and Struts 1.3 framework with Java.

 Here's what you will need in your project:

Files under Web App Libraries:
jackson-annotations-2.4.0.jar
jackson-core--2.4.2.jar
jackson-databind-2.4.2.jar

File under \WebContent\js:
jquery-1.11.1.min.js


In struts-config.xml:
     <action path="/updateParentInvoice"
       type="com.mycompany.action.UpdateParentInvoiceAjaxAction"
       scope="request"   
       input="/jsp/error.jsp"
       validate="false">      
     </action> 

In your javascript:
function updateParentInvoice(remitItemCode, invoiceNo, selectTagElement) {
 var parentInvoiceNo = selectTagElement.options[selectTagElement.selectedIndex].value;
 
    $.ajax({
        type: "GET",
        url: "/{myAppContext}/updateParentInvoice.do",
        //Data to be sent to the server. It is converted to a query string, if not already a string. 
        //For GET-requests, it's appended to the url. For POST-requests, it is sent as Form properties. 
        //Object must be Key/Value pairs
        data: {"remitItemCode":remitItemCode, "invoiceNo":invoiceNo, "parentInvoiceNo":parentInvoiceNo}, 
        //use this default content type when sending data to the server, which is fine for most cases.
        contentType: "application/x-www-form-urlencoded; charset=UTF-8",
        //dataType is type of data that you're expecting back from the server
        dataType: "text",        
        success: function(response){
         alert("response from ajax call \n" + response);
        },
        error: function(e){
            //alert('Error: ' + e);
        }
    }); 
}


In your jsp:
<select id='parentInvSelect-<c:out value="${invoiceNo}"/>' class="invSelect" name="<c:out value="${customerName}" />" onchange="updateParentInvoice('<c:out value="${remitItemCode}" />', '<c:out value="${invoiceNo}" />', this);">
 <option value="">Select One</option>
 <c:forEach var="parentInvoiceNo" items="${invoiceVB.parentInvoiceList}">            
  <option value='<c:out value="${parentInvoiceNo}" />'><c:out value="${parentInvoiceNo}" /></option>  
 </c:forEach>
</select>


In action class (UpdateParentInvoiceAjaxAction.java):
package com.mycompany.action.action;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import com.util.LogHelper;


/*
 *  Author; Eric Soriano
 *  
 *  
 */
public class UpdateParentInvoiceAjaxAction extends Action {
 
 private static final LogHelper LOG = new LogHelper(IncentiveRequestUpdateParentInvoiceAjaxAction.class);
 
 public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
  LOG.debug("START");
  
  String remittanceItemCode = (String)request.getParameter("remitItemCode");
  String invoiceNo = (String)request.getParameter("invoiceNo");
  String parentInvoiceNo = (String)request.getParameter("parentInvoiceNo");
  LOG.debug("Ajax request parameters received: remittanceItemCode = " + remittanceItemCode + " invoiceNo = " + invoiceNo + " parentInvoiceNo = " + parentInvoiceNo );
  
  //add code here to update parentInvoiceNo to the db
  
  response.setContentType("text/text;charset=utf-8");
  response.setHeader("cache-control", "no-cache");
  PrintWriter out = response.getWriter();
  out.println("remittanceItemCode = " + remittanceItemCode + " invoiceNo = " + invoiceNo + " parentInvoiceNo = " + parentInvoiceNo);
  out.flush();
  
  //since this is an ajax call, just return null so that struts does not take any further action
  return null;
 }

}



That's it. Very simple.


Monday, March 30, 2015

Javascript Example: Convert Input Text To Uppercase Characters

This javascript example converts input text to uppercase characters.

<!DOCTYPE html>
<html>
<body>

Enter your name: <input type="text" id="inputBox" onkeyup="convertText()">

<script>
function convertText() {
    var iBox = document.getElementById("inputBox");
    iBox.value = iBox.value.toUpperCase();
}
</script>

</body>
</html>


Reference: onkeyup Event

Saturday, February 28, 2015

Java Application Configuration Using XML

The is a simple tutorial in configuring your Java application using XML files.

For other options in configuring your Java application, please see the link at the end of this tutorial.

Here it goes:

1. Create the xml file for your configuration data.

EmailConfig.xml
<?xml version="1.0" encoding="UTF-8"?>
<config-dTO xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
 <!-- FOR EMAIL -->
 <smtp-host xsi:type="java:java.lang.String">email.mysite.com</smtp-host>
 <system-email-address xsi:type="java:java.lang.String">admin@mysite.com</system-email-address>
 <email-subject xsi:type="java:java.lang.String">Your Daily Update</email-subject>
 <email-body xsi:type="java:java.lang.String">Please see the attached report.</email-body> 
 <recipient-email-list xsi:type="java:java.lang.String">person1@gmail.com,person2@gmail.com</recipient-email-list>
</config-dTO>


2. Create the Java class file that will map to the xml file. Place file in the Business package of the app.

ConfigDTO.java
public class ConfigDTO implements Serializable {
 
 private static final long serialVersionUID = 1L;
 
 //for email sender service
 private String smtpHost = null;
 private String systemEmailAddress = null;
 private String emailSubject = null;
 private String emailBody = null;
 private String recipientEmailList = null ;

 
 public String getSmtpHost() {
  return smtpHost;
 }
 public void setSmtpHost(String smtpHost) {
  this.smtpHost = smtpHost;
 }
 public String getSystemEmailAddress() {
  return systemEmailAddress;
 }
 public void setSystemEmailAddress(String systemEmailAddress) {
  this.systemEmailAddress = systemEmailAddress;
 }
 public String getEmailSubject() {
  return emailSubject;
 }
 public void setEmailSubject(String emailSubject) {
  this.emailSubject = emailSubject;
 }
 public String getEmailBody() {
  return emailBody;
 }
 public void setEmailBody(String emailBody) {
  this.emailBody = emailBody;
 }
 public String getRecipientEmailList() {
  return recipientEmailList;
 }
 public void setRecipientEmailList(String recipientEmailList) {
  this.recipientEmailList = recipientEmailList;
 }
}


3. Create your utility class that will unmarshall the xml data into the corresponding Java class. Place this file in the Business package of your app.

ConfigUtil.java
public class ConfigUtil {

 /**
  * @throws ValidationException 
  * @throws MarshalException 
  * 
  */
 public ConfigUtil() throws MarshalException, ValidationException {
 }
 
 public ConfigDTO getConfigDTO() throws MarshalException, ValidationException {
          
            InputStream inputStream = getClass().getResourceAsStream("/EmailConfig.xml");
        
            InputSource xmlInput = new InputSource(inputStream);
          
     ConfigDTO config = (ConfigDTO) Unmarshaller.unmarshal(ConfigDTO.class, xmlInput);
  
     return config;
 }
}


4. Use the utility class ConfigUtil in your java and servlet classes to get the java class (with the xml data) ConfigDTO.

EmailReport.java
public class EmailReport  {
  
 public void getEmailProps {
 
  ConfigDTO configDTO = new ConfigUtil.getConfigDTO();
  
  System.out.println(configDTO.getSmtpHost());
  System.out.println(configDTO.getSystemEmailAddress());
  System.out.println(configDTO.getEmailSubject());
  System.out.println(configDTO.getEmailBody());
  System.out.println(configDTO.getRecipientEmailList());
 } 
}



Here are various configuration APIs to consider:

1. java.util.Properties

If your configuration properties are just simple key-value pairs, then you might want to try java.util.Properties. If you have lists or maps, you may want to consider the other APIs in this list.

2. Apache Commons Configuration

Apache Commons Configuration allows having the configuration stored in a wide range of formats including properties, XML, JNDI, and more. It is easy to use and to extend. To get the most flexibility out of it use a factory to get the configuration and just use the Configuration interface after that.

3. XStream

XStream is a simple library to serialize objects to XML and back again. It is easy to extend  so that you make the file look the way you want. You can set up aliases for your class and even custom data formats to make the XML file more readable.

4. Apache Commons Digester.

The Digester API lets you configure an XML -> Java object mapping module, which triggers certain actions called rules whenever a particular pattern of nested XML elements is recognized. A rich set of predefined rules is available for your use, or you can also create your own.

5. JFig

6. JConfig

Saturday, January 31, 2015

Quartz 2 Scheduler Tutorial

Quartz is an open source job scheduling library for Java.

This tutorial will show you how to  implement a job scheduler in your Java enterprise project using Quartz 2.

The Quartz scheduler in this tutorial triggers a job that send out email.

1. Download Quartz

The Quartz library is available for download from the Quartz website.

Put the following files into your EAR lib folder.

  1. c3p0-0.9.1.1
  2. log4j-1.2.16
  3. quartz-2.2.1
  4. quartz-jobs-2.2.1
  5. slf4j-api-1.6.6
  6. slf4j-log4j12-1.6.6


2. Create your quartz properties file 

I named my properties file with the project name, such as quartz_dmowgs.properties.

You may name it as quart.properties but I just prefer including the name of the project to the quartz properties' filename.

Configure the Quartz Scheduler in this properties file.

This properties file should be located in your classpath (eg., your WEB project's src folder). 

Configure the plugin in this file with your job's xml filename eg.; quartz_dmowgs.xml
Declare your job's xml file here.

Here is the quartz_dmowgs.properties file. 

#============================================================================
# Configure Main Scheduler Properties  
#============================================================================

org.quartz.scheduler.instanceName = TestScheduler
org.quartz.scheduler.instanceId = AUTO
org.quartz.scheduler.threadsInheritContextClassLoaderOfInitializer = true
org.quartz.scheduler.skipUpdateCheck = true

#============================================================================
# Configure ThreadPool  
#============================================================================

org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 1
org.quartz.threadPool.threadPriority = 5

#============================================================================
# Configure JobStore  
#============================================================================

org.quartz.jobStore.misfireThreshold = 60000

org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore

#============================================================================
# Configure Plugins 
#============================================================================

org.quartz.plugin.triggHistory.class = org.quartz.plugins.history.LoggingJobHistoryPlugin

org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin
org.quartz.plugin.jobInitializer.fileNames = quartz_dmowgs.xml
org.quartz.plugin.jobInitializer.failOnFileNotFound = true
org.quartz.plugin.jobInitializer.scanInterval = 3000
#org.quartz.plugin.jobInitializer.scanInterval = 30
org.quartz.plugin.jobInitializer.wrapInUserTransaction = false

The quartz_dmowgs.xml file contain the xml definition of jobs and associated triggers.
Configure the jobs and triggers that the scheduler will run in this job's xml file.



3.  Declare your QuartzInitializer servlet in the web.xml file.

The QuartzInitializer servlet is used to initialize Quartz, if configured as a load-on-startup servlet in a web application.

Declare your quartz properties (quartz_dmowgs.properties) file as the value for the config-file property of your servlet.

   <servlet> 
    <servlet-name>QuartzInitializer</servlet-name> 
    <servlet-class>org.quartz.ee.servlet.QuartzInitializerServlet</servlet-class> 
    <init-param>
      <param-name>shutdown-on-unload</param-name>
      <param-value>true</param-value>
    </init-param>
    <init-param>
   <param-name>config-file</param-name>
   <param-value>quartz_dmowgs.properties</param-value>
  </init-param>
  <init-param>
   <param-name>start-scheduler-on-load</param-name>
   <param-value>true</param-value>
  </init-param>
  <load-on-startup>3</load-on-startup>
 </servlet>


Declare the other servlets that your job will use.

The EmailReportServlet declared below will be used by the scheduled job to send emails.

 <servlet>
  <description>
  </description>
  <display-name>EmailReportServlet</display-name>
  <servlet-name>EmailReportServlet</servlet-name>
  <servlet-class>com.eric.web.servlet.EmailReportServlet</servlet-class>
 </servlet>



Don't forget the mappings:

 <servlet-mapping>
  <servlet-name>QuartzInitializer</servlet-name>
  <url-pattern>/QuartzInitializer</url-pattern>
 </servlet-mapping> 
 <servlet-mapping>
  <servlet-name>EmailReportServlet</servlet-name>
  <url-pattern>/EmailReportServlet</url-pattern>
 </servlet-mapping>




4. Create your QuartzStrutsPlugin class within a package in your src folder.

A PlugIn is a configuration wrapper for a module-specific resource or service that needs to be notified about application startup and application shutdown events (corresponding to when the container calls init and destroy on the corresponding ActionServlet instance). PlugIn objects can be configured in the struts-config.xml file.

Here is the QuartzStrutsPlugin class.

import javax.servlet.ServletException;

import org.apache.struts.action.ActionServlet;
import org.apache.struts.action.PlugIn;
import org.apache.struts.config.ModuleConfig;
import org.quartz.Scheduler;
import org.quartz.impl.StdSchedulerFactory;



public class QuartzStrutsPlugin implements PlugIn {

 /* (non-Javadoc)
  * @see org.apache.struts.action.PlugIn#destroy()
  */
 public void destroy() {
  // TODO Auto-generated method stub
  
 }

 /* (non-Javadoc)
  * @see org.apache.struts.action.PlugIn#init(org.apache.struts.action.ActionServlet, org.apache.struts.config.ModuleConfig)
  */
 public void init(ActionServlet arg0, ModuleConfig arg1)
   throws ServletException {
  try {
   StdSchedulerFactory sf = new StdSchedulerFactory();

   sf.initialize("quartz_dmowgs.properties");

   Scheduler scheduler = sf.getScheduler();
   scheduler.start();

  } catch (Exception e) {
    System.out.println("Error starting Quartz Scheduler: " + e.getMessage());
    e.printStackTrace();

  }

  
 }

}



5. Declare the QuartzStrutsPlugin in the struts-config.xml file.

 <plug-in className="com.eric.web.plugin.QuartzStrutsPlugin">
 </plug-in>



6.  Create quartz_dmowgs.xml  - the xml file that defines the scheduled job.

The quartz_dmowgs.xml file contain the xml definition of jobs and associated triggers.
Configure the jobs and triggers that the scheduler will run in its xml file.

Here is the quartz_dmowgs.xml file.

<?xml version="1.0" encoding="UTF-8"?>
<job-scheduling-data xmlns="http://www.quartz-scheduler.org/xml/JobSchedulingData"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.quartz-scheduler.org/xml/JobSchedulingData http://www.quartz-scheduler.org/xml/job_scheduling_data_1_8.xsd"
    version="1.8">
    
    <pre-processing-commands>
        <delete-jobs-in-group>*</delete-jobs-in-group>  <!-- clear all jobs in scheduler -->
        <delete-triggers-in-group>*</delete-triggers-in-group> <!-- clear all triggers in scheduler -->
    </pre-processing-commands>
    
    <processing-directives>
        <!-- if there are any jobs/trigger in scheduler of same name (as in this file), overwrite them -->
        <overwrite-existing-data>true</overwrite-existing-data>
        <!-- if there are any jobs/trigger in scheduler of same name (as in this file), and over-write is false, ignore them rather then generating an error -->
        <ignore-duplicates>false</ignore-duplicates> 
    </processing-directives>
    
    <schedule>
     <job>
         <name>EmailReportJob</name>
         <description>Job to generate and email reports</description>
         <job-class>com.eric.wgs.quartz.job.EmailReportJob</job-class>
          <job-data-map>
              <entry>
                  <key>url</key>
                  <value>http://localhost:9084/DMOWGSWeb/EmailReportServlet</value>
              </entry>
              <entry>
                  <key>host</key>
                  <value>localhost</value>
              </entry>              
              <entry>
                  <key>user</key>
                  <value>wasadmin</value>
              </entry>
              <entry>
                  <key>password</key>
                  <value>password123</value>
              </entry>              
       </job-data-map>
     </job>
     <trigger>
           <cron>
             <name>CronTriggerForEmail</name>
             <job-name>EmailReportJob</job-name>
             <start-time>2014-07-31T11:00:00.0</start-time> 
             <end-time>2015-12-31T12:26:00.0</end-time> 
             <misfire-instruction>MISFIRE_INSTRUCTION_SMART_POLICY</misfire-instruction>
             <cron-expression>0 0 8-19 * * ?</cron-expression>
          </cron>
     </trigger>     
    </schedule>    
</job-scheduling-data>




7. Create your job class - EmailReportJob.java

This job will generate and email reports. 

This job generates and email reports by invoking the EmailReportServlet through  the job-data-map property values from the quartz property file quartz_dmowgs.xml.

It uses the JobExecutionContext class of Quartz to get the job-data-map property values.

It also uses the Base64 class to encode the user and password credentials.


Here is the EmailReportJob.java code.


/**
 * @author Eric Soriano
 *
 * This job will generate and email reports
 * 
 */
public class EmailReportJob implements Job {

 private final LogHelper LOG = new LogHelper(this.getClass());

 private URL myURL = null;
 private URLConnection connection = null;

 public void execute(JobExecutionContext context) throws JobExecutionException {
  DefaultHttpClient httpclient = new DefaultHttpClient();
    
  try {   
   JobDataMap data = context.getJobDetail().getJobDataMap();
   String url = data.getString("url"); 
   String host = data.getString("host");
   String user = data.getString("user");
   String pwd = data.getString("password");   
    
   String credentials = user + ":" + pwd;   
   //encode credentials into base 64
   byte[] encoded = Base64.encodeBase64(credentials.getBytes()); 
   String encodedCred = new String(encoded);
  
   //invoke the servlet url (EmailReportServlet - see quartz_dmowgs.xml)
   myURL = new URL(url);
   connection = myURL.openConnection();
   
   //set credentials into URLConnection object
   connection.setRequestProperty("Authorization", String.format("Basic %s", encodedCred)); 
   
   InputStream response = connection.getInputStream();
   
   
  } catch (MalformedURLException mfURLe) {
   LOG.error("execute :: MalformedURLException: " + mfURLe.getMessage());
   mfURLe.printStackTrace();  
  } catch (Exception ex) {
   LOG.error("execute :: HTTP Exception: " + ex.getMessage());
   JobExecutionException e2 = 
          new JobExecutionException(ex);
         throw e2;
  }
 }


 
}


8. Create your servlet - EmailReportServlet.java

This servlet creates an Excel report then uses a EmailSenderService class that uses a EmailDAO class to email the report.

Here is the code for EmailReportServlet.java.


package com.eric.wgs.web.servlet;

public class EmailReportServlet extends HttpServlet  {
 
 private static final long serialVersionUID = 1L;
 private final LogHelper LOG = new LogHelper(this.getClass());
 
 
 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  String method = "doGet()";
  LOG.debug(method, "START");
  
  try {  
   //Create the report (excel file) with the executeTask() method and send as ByteArrayOutputStream object to EmailSenderService
   ByteArrayOutputStream baos = executeTask(request);
   
   //Check if baos is null (intentionally set to null from CompanyProgressReportServiceBean when recipient email list is empty)
   if (baos == null) {
    LOG.debug(method, "ByteArrayOutputStream is null");
    return;
   }
   if(baos != null && baos.size() > 0) {   
    //email the report
    EmailSenderService emailService = new EmailSenderService();
    emailService.sendEmailWithAttachment(baos);    
   } else {
    throw new ApplicationException("executeTask method returned unexpected results: " + baos);
   }   
  } catch(Exception ex) {
   ex.printStackTrace();
   LOG.error("Exception Generating PDF: " + ex.getMessage());
   throw new ServletException(ex);
  }
 } 

 public ByteArrayOutputStream executeTask(HttpServletRequest request) throws IOException, ServletException, ApplicationException {
  String method = "executeTask()";
  LOG.debug(method, "START");
  
  ByteArrayOutputStream buffer = null;
  try {
   ConfigDTO config = new ConfigUtil().getConfig();
   //if ConfigDTO.recipientEmailList is null, return a null ByteArrayOutputStream so report will not be generated and emailed
   if (config.getRecipientEmailList() == null || config.getRecipientEmailList().equals("") ) {
    buffer = null;
    LOG.debug(method, "Recipient email list is null so returning a null baos. Report will not be generated and not emailed.");
    return buffer;    
   }   
      
   //Get the data from the DAO using the service
   CompanyProgressReportServiceBean service = CompanyProgressReportServiceBean.getIntance();
   CompanyProgressReportDTO results = service.getReport();   
      
   //Once I have the results, create workbook using utility
   CompanyProgressReportGeneratorUtil rptUtil = new CompanyProgressReportGeneratorUtil();
   //Workbook wb = rptUtil.createReportExcel(results);
   Workbook wb = rptUtil.createReportExcel(results);   
   
   //Finally add the workbook to the baos to be returned
   buffer = new ByteArrayOutputStream();
   //wb = get me the excel
   wb.write(buffer);
    
  } catch (IOException e) {
   LOG.error(e.getMessage());
   e.printStackTrace();
   throw new ServletException(e.getMessage());
  } catch (Exception e) {
   LOG.error(e.getMessage());
   e.printStackTrace();
   throw new ServletException(e.getMessage());
  }
  LOG.debug(method, "END");
  return buffer;
 } 
 
}