About nobukimi@gmail.com

I’ve been working on Java developer for 15+ years. Hope this website shares my experiences for developing and maintaining business web apps.

Generic DAO without Custom Method

db-chain1
Instead of having DAO for each entity, calling Generic DAO simplify the program. (Source Code)

2015-05-30_09h48_00

2015-05-30_09h53_38

package com.ns.spring.dao.template;

import com.ns.spring.dao.GenHbDao;
import com.ns.spring.model.MDSE;

public interface MdseDao extends GenHbDao<MDSE, String> {

}
package com.ns.spring.dao.template.impl;

import org.springframework.stereotype.Repository;

import com.ns.spring.dao.GenHbDaoImpl;
import com.ns.spring.dao.template.MdseDao;
import com.ns.spring.model.MDSE;

@Repository
public class MdseDaoImpl extends GenHbDaoImpl<MDSE, String> implements MdseDao {

}

Empty DAO interface, and it’s implementation

package com.ns.spring.service.template;

import com.ns.spring.model.MDSE;
import com.ns.spring.service.GenHbService;

public interface MdseService extends GenHbService<MDSE, String> {

}

package com.ns.spring.service.template.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import com.ns.spring.dao.GenHbDao;
import com.ns.spring.dao.template.MdseDao;
import com.ns.spring.model.MDSE;
import com.ns.spring.service.GenHbServiceImpl;
import com.ns.spring.service.template.MdseService;

@Service("mdseService")
public class MdseServiceImpl extends GenHbServiceImpl<MDSE, String> implements MdseService {

	private MdseDao dao;

	public MdseServiceImpl() {
	}

	@Autowired
	public MdseServiceImpl(@Qualifier("mdseDaoImpl") GenHbDao<MDSE, String> genericDao) {
		super(genericDao);
		this.dao = (MdseDao) genericDao;
	}
}

Empty DAO service interface, and it’s implementation calling super class. It can use the method defined in Generic DAO

Auto Complete

autocomplete3
In Biz web apps, an end user often need to enter some code that he/she cannot memorize. For for example, a product code. And auto complete is very helpful and it is a commonly used in Ajax.

Summarized as two steps

  1. Javascript function is being called every time a key stroked on keyboard
  2. Ajax calls a controller class and the controller class returns a suggested list

2015-05-29_07h14_55


1. Javascript function is being called every time a key stroked on keyboard

<form:input path="mdseCd" id="idItemCd" style="height:25px; width:200px" />

Step 1.1. Javascript (Ajax) will be called as user types a key

$('#idItemCd').autocomplete({
   serviceUrl: '${pageContext.request.contextPath}/autoCompleteList',
   paramName: "inputVal",
   delimiter: ",",
   transformResult: function(response) {
       return {
           suggestions: $.map($.parseJSON(response), function(item) {
               return {
                   value: item.mdseCd,
                   data: item.id
               };
           })
       };
   }
});

Step 1.2. This Ajax send a request to the controller method:


2. Ajax calls a controller class and the controller class returns a suggested list

@RequestMapping(value = "/autoCompleteList", method = RequestMethod.GET)
public @ResponseBody List<MdseModel> getTags(@RequestParam(value = "inputVal") String inputVal, HttpServletRequest req) {
	List<MdseModel> entireSessionList = (List<MdseModel>)req.getSession().getAttribute(CONST.MDSE_LIST.getVal());
	List<MdseModel> resultList = new ArrayList<MdseModel>();
	if (!CommonBL.isEmpty(entireSessionList)) {
		for (MdseModel obj : entireSessionList) {
			// Fuzzy search
			if (obj.getMdseCd().contains(inputVal)) {
				resultList.add(obj);
			}
		}
	}
	return resultList;
}

Step 2.1. At line 3, getting a entireSessionList contains an entire list that has been created as the screen is initialized.
2015-05-30_08h10_19
Step 2.2. At line 8 to 10, the method creating a list that starts from “5508
Step 2.3. At line 13, the method returns the list as JSON object.

Multiple Row Form Submit

submit-multi-form2
In biz apps, it is a common requirement that the data stays in the screen but not in the data base. And it’s pretty painful, compared to insert the record every time the user add it.

Suppose your screen displaying a list, and you have added more than one rows at once (But not in the Database yet)
submit-multiple-rows1
Once submitted, the added rows are in the Database:
submit-multiple-rows2

Summarized as two steps:

  1. The each row added one by one in the screen
  2. All rows are inserted/updated to the Database

@RequestMapping(value = "/cUrlValAttrbSubLine01Jsp", params = "addItemSubLine01", method = RequestMethod.POST)
public ModelAndView addItemSubLine01(@ModelAttribute("rmaLineListModel") RmaLineListModel rmaLineListModel, Model model, HttpServletRequest req) {
	
	ModelAndView modelAndView = new ModelAndView(VIEW.SUB_LINE_01.getVal());
	modelAndView.addObject(CONST.FORM_KEY.getVal(), rmaLineListModel);

	String rmaNum = rmaLineListModel.getRmaNum();
	String mdseCd = rmaLineListModel.getMdseCd();
	String mdseNm = CommonBL.getMdseNm(CommonBL.getMdse(mdseCd));
	List<RmaLineModel> currList = rmaLineListModel.getRmaLineModelList();
	
	RmaLineModel newRow = new RmaLineModel();
	newRow.setRmaNum(rmaNum);
	newRow.setRmaLineNum(RmaDtlBL.getNewLineNum(currList));
	newRow.setMdseCd(mdseCd);
	newRow.setMdseNm(mdseNm);
	currList.add(newRow);
	
	rmaLineListModel.setRmaLineModelList(currList);		
	modelAndView.addObject(CONST.LINE_LIST_MODEL.getVal(), rmaLineListModel);
	modelAndView.addObject(CONST.HDR_STS_LIST.getVal(), CommonBL.getStsList(req));	
	return modelAndView;
}

At Step 1, in the Controller method, line between 12 to 17, adding a new Object added to the list

@RequestMapping(value = "/cUrlValAttrbSubLine01Jsp", params = "submitLine", method = RequestMethod.POST)
public ModelAndView submitLine(@ModelAttribute("rmaLineListModel") RmaLineListModel rmaLineListModel, Model model, HttpServletRequest req) {

	String rmaNum = rmaLineListModel.getRmaNum();
	List<RmaLineModel> currList = rmaLineListModel.getRmaLineModelList();
	if (!CommonBL.isEmpty(currList)) {
		for (RmaLineModel obj : currList) {
			String rmaLineNum = obj.getRmaLineNum();
			List<RmaLineModel> rmaLinsList = RmaDtlBL.getRmaLineListWithCdTblNm(rmaNum, rmaLineNum);
			if (CommonBL.isEmpty(rmaLinsList)) {
				// New Record
				this.rmaLineSvc.save(RmaDtlBL.getRmaLineObj(obj, rmaNum, rmaLineNum));
			}
		}
	}
	List<RmaLineModel> rmaLineModelList = RmaDtlBL.getRmaLineListWithCdTblNm(rmaNum, null);
	return getMVSubLine01(rmaNum, rmaLineModelList, req);
}

At Step 2, in the Controller, it takes a parameter (Model class) contains a list, and the three added rows are now added.

HTML Table Creation

hdr-ajax-tempate3
More biz web apps are using Javascript because of its capability; Handling an event.
In this example, the HTML tables are constructed on changing event of select box.

Summary

  • The table on left side constructed by a result of SQL (as select box value has been changed)
  • The table on right side constructed by a result of different SQL (at the same time of when the one in the left constructed)

dinamic-table-creation-result2
compare-two-tables1

Summarized as Four steps

  1. Select box has changed and the Javascript (Ajax) send request to the Controller
  2. The Controller method create a object for two tables (LEFT and RIGHT) and send back response
  3. Javascript (Ajax) receives a response and construct two set of HTML
  4. Two HTML tables (LEFT and RIGHT) are created by jQuery

1. Select box has changed and the Javascript (Ajax) send request to the Controller

<form:select path="rtrnTpCd" id="tpCd" onchange="onChangeTp();" style="height:25px; width:200px">
   <form:option value="" label="--- Select Type ---"/>
   <c:forEach items="${TP_LIST}" var="name">
      <c:choose>
         <c:when test="${name.getRtrnTpCd()== TP_SELECTED}">
            <form:option value="${name.getRtrnTpCd()}" selected="true">${name.getRtrnTpNm()}</form:option>
         </c:when>
         <c:otherwise>
            <form:option value="${name.getRtrnTpCd()}">${name.getRtrnTpNm()}</form:option>
         </c:otherwise>
      </c:choose>
   </c:forEach>
</form:select>

Step 1.1. At line 1, when select box is selected, it’s calling Javascript function “onChangeTp()“.

function onChangeTp() {
   var selectedTpCd = $('#tpCd').val();
   $.ajax({
      type : "Get", 
      url : "onChangeTpCdTpRsn01",
      data : "tpCd=" + selectedTpCd,
      success : function(response) {
         // Remove the row excluding the first row
         $("#idTableRsnBound").find("tr:gt(0)").remove();
         $("#idTableRsnUnBound").find("tr:gt(0)").remove();
         var trHtmlBound = '';
         var trHtmlUnBound = '';
         $.each(response, function(k, v) {
            var thisTpCd = v.rtrnTpCd;
            if(thisTpCd == selectedTpCd) {
               trHtmlBound = getRsnLines(trHtmlBound, k, v);
            } else {
               trHtmlUnBound = getRsnLines(trHtmlUnBound, k, v);
            }
         });
         $('#idTableRsnBound').append(trHtmlBound);
         $('#idTableRsnUnBound').append(trHtmlUnBound);
      },
      error : function(e) {
         alert('Error onChangeTp: ' + e);
      }
   });
}

Step 1.2. At line 5, the Ajax request for the controller “onChangeTpCdTpRsn01“.


2. The Controller method create a object for two tables (LEFT and RIGHT) and send back response

@RequestMapping(value = "/onChangeTpCdTpRsn01")
public @ResponseBody List<RtrnRsnModel> refreshTypeComb(@RequestParam(value = "tpCd") String rtrnTpCd, Model model, HttpServletRequest req) {

	model.addAttribute(CONST.FORM_KEY.getVal(), new RtrnTpModel());
	model.addAttribute("rtrnTpCd", rtrnTpCd);
	model.addAttribute(CONST.TP_SELECTED.getVal(), rtrnTpCd);
	req.getSession().setAttribute(CONST.TP_SELECTED.getVal(), rtrnTpCd);
	initBoundUnboundRsnList(rtrnTpCd, req);

	List<RtrnRsnModel> rsnBoundList = (List<RtrnRsnModel>)req.getSession().getAttribute(CONST.RSN_LIST_BOUND.getVal());
	List<RtrnRsnModel> rsnUnBoundList = (List<RtrnRsnModel>)req.getSession().getAttribute(CONST.RSN_LIST_UNBOUND.getVal());
	List<RtrnRsnModel> rsnList = new ArrayList<RtrnRsnModel>();
	TpRsnBL.setNewRsnList(rsnList, rsnBoundList);
	TpRsnBL.setNewRsnList(rsnList, rsnUnBoundList);
	return rsnList;
}

Step 2.1. At line 10, set the SQL result for the LEFT SIDE table.
Step 2.2. At line 11, set the SQL result for the RIGHT SIDE table.

[
	Reason Code:001, Name:Item Damaged, Type:01,
	Reason Code:002, Name:Did not order, Type:01,
	Reason Code:003, Name:Customer has moved, Type:01,
	Reason Code:004, Name:Cancelled by customer, Type:01,
	Reason Code:007, Name:Customer did not like it, Type:01,
	Reason Code:005, Name:Customer being bunkrupt, Type:,
	Reason Code:006, Name:Defective Item, Type:,
	Reason Code:008, Name:Duplicated order, Type:,
	Reason Code:009, Name:Change his/her mind, Type:,
	Reason Code:010, Name:Item lost, Type:,
	Reason Code:011, Name:Wrong address, Type:,
	Reason Code:012, Name:Wrong Item, Type:
]

Step 2.3. At line 15, return as one object (ABOVE) combined LEFT and RIGHT tables.

NOTE: Line 2 to 6 ends with “Type:01” will be the LEFT table


3. Javascript (Ajax) receives a response and construct two tables

function onChangeTp() {
   var selectedTpCd = $('#tpCd').val();
   $.ajax({
      type : "Get", 
      url : "onChangeTpCdTpRsn01",
      data : "tpCd=" + selectedTpCd,
      success : function(response) {
         // Remove the row excluding the first row
         $("#idTableRsnBound").find("tr:gt(0)").remove();
         $("#idTableRsnUnBound").find("tr:gt(0)").remove();
         var trHtmlBound = '';
         var trHtmlUnBound = '';
         $.each(response, function(k, v) {
            var thisTpCd = v.rtrnTpCd;
            if(thisTpCd == selectedTpCd) {
               trHtmlBound = getRsnLines(trHtmlBound, k, v);
            } else {
               trHtmlUnBound = getRsnLines(trHtmlUnBound, k, v);
            }
         });
         $('#idTableRsnBound').append(trHtmlBound);
         $('#idTableRsnUnBound').append(trHtmlUnBound);
      },
      error : function(e) {
         alert('Error onChangeTp: ' + e);
      }
   });
}

Step 3.1. At line 7, get the response from the controller (one list as JSON object)
Step 3.2. At line 9 and 10, clear the LEFT and RIGHT to be re-constructed

function getRsnLines(trHtml, idx, dataObj) {
   //Get each key and value from the list
   var code = dataObj.rtrnRsnCd;
   var val = dataObj.rtrnRsnNm;
   trHtml +=
	      '<tr>'
	      + '<td>'
	      +   '<input id="selectedCheckBox'+idx+'" name="selectedCheckBox" type="checkbox" value="'+code+'"/>'
	      + '</td>'
	      + '<td>'+code+'</td>'
	      + '<td>'+val+'</td>'
	      +'</tr>';
   return trHtml;
}

Step 3.3. At line 15 to 19, create two HTML tables (LEFT and RIGHT) by function “getRsnLines” (above).


4. Two HTML tables (LEFT and RIGHT) are created by jQuery

function onChangeTp() {
   var selectedTpCd = $('#tpCd').val();
   $.ajax({
      type : "Get", 
      url : "onChangeTpCdTpRsn01",
      data : "tpCd=" + selectedTpCd,
      success : function(response) {
         // Remove the row excluding the first row
         $("#idTableRsnBound").find("tr:gt(0)").remove();
         $("#idTableRsnUnBound").find("tr:gt(0)").remove();
         var trHtmlBound = '';
         var trHtmlUnBound = '';
         $.each(response, function(k, v) {
            var thisTpCd = v.rtrnTpCd;
            if(thisTpCd == selectedTpCd) {
               trHtmlBound = getRsnLines(trHtmlBound, k, v);
            } else {
               trHtmlUnBound = getRsnLines(trHtmlUnBound, k, v);
            }
         });
         $('#idTableRsnBound').append(trHtmlBound);
         $('#idTableRsnUnBound').append(trHtmlUnBound);
      },
      error : function(e) {
         alert('Error onChangeTp: ' + e);
      }
   });
}

At line 21 and 22, two set of HTML will be set to the ID specified:

<div class="id_Bound">
<table id="idTableRsnBound" class="tg" border="1">
	<tr>
		<th width="20"></th>
		<th width="80">Reason Code</th>
		<th width="120">Reason Name</th>
	</tr>							
	<c:forEach items="${RSN_LIST_BOUND}" var="rsnVal" varStatus="loop">
		<tr>
			<td><form:checkbox path="selectedCheckBox" value="${rsnVal.rtrnRsnCd}"/></td>
			<td>${rsnVal.rtrnRsnCd}</td>
			<td>${rsnVal.rtrnRsnNm}</td>
		</tr>
	</c:forEach>
</table>
</div>

Step 4.1. At line 21, create (set HTML) to the table on the LEFT (#idTableRsnBound)

<div class="id_UnBound">
<table id="idTableRsnUnBound" class="tg" border="1">
	<tr>
		<th width="20"></th>
		<th width="80">Reason Code</th>
		<th width="120">Reason Name</th>
	</tr>
	<c:forEach items="${RSN_LIST_UNBOUND}" var="rsnVal" varStatus="loop">
		<tr>
			<td><form:checkbox path="selectedCheckBox" value="${rsnVal.rtrnRsnCd}"/></td>
			<td>${rsnVal.rtrnRsnCd}</td>
			<td>${rsnVal.rtrnRsnNm}</td>
		</tr>
	</c:forEach>
</table>
</div>

Step 4.2. At line 22, create (set HTML) to the table on the RIGHT (#idTableRsnUnBound)

Submitting a Form

submit-form-img1
Unlike updating a part of screen by Ajax, this is a traditional(?), and a basic way: to Submit an entire form.

Summarized as three steps:

  1. SUBMIT button is pressed, and passes an Forms (Object) to the controller method.
  2. The Controller method takes the Object and Register (Insert/Update) to the data base
  3. Return a String as JSP name

The Detail of Step 1
submit-form-take-param1

@RequestMapping(value = "/cUrlValAttrbMain01Jsp", params = "submitHdr", method = RequestMethod.POST)
public String submitHdr(@ModelAttribute("RmaHdrModel") RmaHdrModel rma, HttpServletRequest req) {
	RmaBL.saveHdr(rma, req);
	return VIEW.REDIRECT_HOME.getVal();
}

1.1.cUrlValAttrbMain01Jsp” is defined in main_01.jsp.

<c:url var="addAction" value="/cUrlValAttrbMain01Jsp.html" ></c:url>
<form:form action="${addAction}" commandName="rmaMapKey">

1.2.submitHdr” is “name” attribute in “Submit” button in main_01.jsp.

<input type="submit" value="Submit" name="submitHdr" style="height:25px; width:150px; color: #F6FDA4; background-color: #CC0000; font-face: 'Comic Sans MS';"/>

1.3. @ModelAttribute specifies an argument in the Controller class RmaController.java.
1.4. The parameter “RmaHdrModel rma” takes the form object from JSP.


The Detail of Step 2 & 3
submit-form-step-2-3

@RequestMapping(value = "/cUrlValAttrbMain01Jsp", params = "submitHdr", method = RequestMethod.POST)
public String submitHdr(@ModelAttribute("RmaHdrModel") RmaHdrModel rma, HttpServletRequest req) {
	RmaBL.saveHdr(rma, req);
	return VIEW.REDIRECT_HOME.getVal();
}

2.1. RmaBL.saveHdr does insert/update to the Database

public static RMA_HDR saveHdr(RmaHdrModel rma, HttpServletRequest req) {
	RMA_HDR obj = new RMA_HDR(rma);
	if (rma.getId() == 0) {
		hdrSvc.save(obj);
		// Set RMA# with formatted
		DecimalFormat df = new DecimalFormat("000000");
		obj.setRmaNum("RMA" + df.format((double) obj.getId()));
	}
	hdrSvc.update(obj);
	req.getSession().removeAttribute(CONST.HDR_LIST.getVal());
	return obj;
}

3.1.VIEW.REDIRECT_HOME.getVal()” returns a string “redirect:/ns-home” from a constant class and redirect to the method initialize the screen

enum VIEW {
	
	MAIN_01("main_01"),
	SUB_LINE_01("sub_line_01"),
	SUB_TP_01("sub_tp_01"),
	SUB_RSN_01("sub_rsn_01"),
	SUB_TP_RSN_01("sub_tp_rsn_01"),
	REDIRECT_HOME("redirect:/ns-home")
	;
	
	private String code;

	VIEW(String code) {
		this.code = code;
	}

	public String getVal() {
		return code;
	}
}

Updating an MVC Partial View

hdr-ajax-partial-update-img1
Unlike submitting a ENTIRE FORM, Ajax web apps is commonly used to update ONLY A PART OF HTML. This section is continued from the previous section.
partial-mvc-update
This example only update one of multiple rows in a HTML:

radio-button-selected-and-copied-img1
(Above image) Copied fields (on the right side) will be registered in Data base and the row in a screen. (Below image)
updated-row1

Summarized as five steps:

  1. Take the form values from the form and call the Javascript (with Ajax) function
  2. Send request to the Controller with the object
  3. The controller receives the request and register the database
  4. The controller response the Ajax with the object
  5. J-Query function update the HTML as response object

2015-05-25_21h12_31
By Pressing this button:

<input type="button" id="idSubmitHdr" value="Update RMA" style="height:25px; width:150px; color: #F6FDA4; background-color: #0400FF; font-face: 'Comic Sans MS';"/>
$(function() {
   $('#idSubmitHdr').on('click',function() {

      var idId = $("#idId").val();
      var idRmaNum = $("#idRmaNum").val();
      var id_tpCd = $("div.id_tpCd select").val();
      var id_RsnCd = $("div.id_RsnCd select").val();
      var idSellTo = $("#idSellTo").val();
      var id_HdrSts = $("div.id_HdrSts select").val();

      var rmaHdrModel = {
         "id" : idId,
         "rmaNum" : idRmaNum,
         "rtrnTpCd" : id_tpCd,
         "rtrnRsnCd" : id_RsnCd,
         "sellToCustCd" : idSellTo,
         "rmaHdrStsCd" :id_HdrSts
      }
      $.ajax({
         type : 'POST', 
         url : 'submitHdrByJsonMain01',
         contentType : 'application/json; charset=utf-8',
         dataType : 'json',
         data: JSON.stringify(rmaHdrModel),
         success : function(data) {
            modifyRowData(data);
         },
         error : function(e) {
            alert("error:" +response+ ":" +e);
         }
      });
   });
});

Step 1. The above Javascript function takes six values from the form, and created as one object (Line 2 and 12 to 17).
Step 2. Send request to the Controller with the object
NOTE: use “JSON.stringify” function (line 24)

@RequestMapping(value = "/submitHdrByJsonMain01", method = RequestMethod.POST)
public @ResponseBody RmaHdrModel submitHdrByJson(@RequestBody RmaHdrModel rma, HttpServletRequest req) {		
	RMA_HDR obj = RmaBL.saveHdr(rma, req);
	return RmaBL.getRmaHdrModel(obj.getRmaNum());
}

Step 3 and 4. The controller receives the request and register the data base and returns a JSON object to Javascript.

function modifyRowData(newData) {
   var id = newData.id;
   var rmaNum = newData.rmaNum;
   var stsCd = newData.rmaHdrStsCd;
   var stsNm = newData.rmaHdrStsNm;
   var tpCd = newData.rtrnTpCd;
   var tpNm = newData.rtrnTpNm;
   var rsnCd = newData.rtrnRsnCd;
   var rsnNm = newData.rtrnRsnNm;
   var custCd = newData.sellToCustCd;

   $('#IdHdrDtl tr').each(function() { 
      var currRmaNum = $(this).find('td').eq(3).text(); // rmaNum
      var currStsCd = $(this).find('td').eq(4).text(); // StsCd
      var currStsNm = $(this).find('td').eq(5).text();
      var currTpCd = $(this).find('td').eq(6).text(); // TpCd
      var currTpNm = $(this).find('td').eq(7).text();
      var currRsnCd = $(this).find('td').eq(8).text(); // RsnCd
      var currRsnNm = $(this).find('td').eq(9).text();
      var currCustCd = $(this).find('td').eq(10).text(); // CustCd

      var idRmaNum = $(this).find('td').eq(3).attr('id');
      var idStsCd = $(this).find('td').eq(4).attr('id');
      var idStsNm = $(this).find('td').eq(5).attr('id');
      var idTpCd = $(this).find('td').eq(6).attr('id');
      var idTpNm = $(this).find('td').eq(7).attr('id');
      var idRsnCd = $(this).find('td').eq(8).attr('id');
      var idRsnNm = $(this).find('td').eq(9).attr('id');
      var idCustCd = $(this).find('td').eq(10).attr('id');

      if(rmaNum == currRmaNum) {
         $("#"+ idStsCd).html(stsCd);
         $("#"+ idStsNm).html(stsNm);
         $("#"+ idTpCd).html(tpCd);
         $("#"+ idTpNm).html(tpNm);
         $("#"+ idRsnCd).html(rsnCd);
         $("#"+ idRsnNm).html(rsnNm);
         $("#"+ idCustCd).html(custCd);
         return false;
      }
   });
}

Step 5. Another Javascript function “modifyRowData” (Above) called and J-Query function update a part of HTML (specified row in this example).

Radio Button Events

radio-button-evegnt1
In business application, it is often common to have Radio Button in a collection.
And the Radio Button has an event handling:
radio-button-selected-and-copied-img1
Summarized as two steps:

  1. The radio button is selected at the specified row, and calls Ajax function, and function calls Controller
  2. The Controller returns the JSON object from Data base, and update the fields by jQuery

1. The radio button is selected at the specified row, and calls Ajax function, and function
selected-radio-button-img3
Step 1.1. At the line 3 of main_01.jsp, “${rmaObj.id}” contains the primary key of RMA_HDR.

<c:forEach items="${HDR_LIST}" var="rmaObj" varStatus="loop">
	<tr height="15">
		<td><form:radiobutton path="radioBtn" class='close clickIdx' data-id='${rmaObj.id}' /></td>
		<td><form:checkbox path="selectedCheckBox" value="${rmaObj.rmaNum}"/></td>
		<td id="id${loop.index}">${rmaObj.id}</td>
		<td id="idRmaNum${loop.index}">${rmaObj.rmaNum}</td>
		<td id="idStsCd${loop.index}">${rmaObj.rmaHdrStsCd}</td>
		<td id="idStsNm${loop.index}">${rmaObj.rmaHdrStsNm}</td>
		<td id="idTpCd${loop.index}">${rmaObj.rtrnTpCd}</td>
		<td id="idTpNm${loop.index}">${rmaObj.rtrnTpNm}</td>
		<td id="idRsnCd${loop.index}">${rmaObj.rtrnRsnCd}</td>				
		<td id="idRsnNm${loop.index}">${rmaObj.rtrnRsnNm}</td>
		<td id="idCustCd${loop.index}">${rmaObj.sellToCustCd}</td>
		<td><a href="<c:url value='/edit/${rmaObj.id}' />" >Edit</a></td>
		<td><a href="<c:url value='/remove/${rmaObj.id}' />" >Delete</a></td>
		<td><a href="<c:url value='/cUrlValSubLine01Jsp/${rmaObj.rmaNum}' />" >Detail</a></td>
	</tr>
</c:forEach>

Step 1.2. Send request by Ajax:

  • close clickIdx” calls the Javascript function (line 2)
  • Set the passing value “number” (line 4) and set request parameter as “idx” (line 9)
  • Set the request” onCheckRadioRmaMain01” (line 7)
$(function() {
   $(document).on('click', '.clickIdx', function() {
      var $this = $(this);
      var number = $this.data('id');
      $.ajax({
         type : 'POST', 
         url : 'onCheckRadioRmaMain01',
         dataType : 'json',
         data : "idx=" + number,
         success : function(data) {
            var id = data.id;
            var rmaNum = data.rmaNum;
            var rtrnTpCd = data.rtrnTpCd;
            var rtrnRsnCd = data.rtrnRsnCd;
            var sellToCustCd = data.sellToCustCd;
            var rmaHdrStsCd = data.rmaHdrStsCd;
            $("#idId").val(id);
            $("#idRmaNum").val(rmaNum);
            $("div.id_tpCd select").val(rtrnTpCd);
            $("div.id_RsnCd select").val(rtrnRsnCd);
            $("#idSellTo").val(sellToCustCd);
            $("div.id_HdrSts select").val(rmaHdrStsCd);
         },
         error : function(e) {
            alert("error:" +response+ ":" +e);
         }
      });
   });
});

2. The Controller returns the JSON object from Data base, and update the fields by jQuery
radio-button-call-controller-param-img1
Step 2.1. Controller method receives the request with parameter value “idx” which is the primary key to get the data from Database
Step 2.2. Return the result from the Database as JSON

@RequestMapping(value = "/onCheckRadioRmaMain01")
public @ResponseBody RmaHdrModel onCheckRadioRma(@RequestParam(value = "idx") int idx, Model model, HttpServletRequest req) {
	RmaHdrModel rmaHdrModel = new RmaHdrModel(this.hdrSvc.findById(idx));
	model.addAttribute(CONST.FORM_KEY.getVal(), rmaHdrModel);
	return rmaHdrModel;
}

Step 2.3. The response (JSON) has been set by jQuery “.val” specified by the field’s ID

$(function() {
   $(document).on('click', '.clickIdx', function() {
      var $this = $(this);
      var number = $this.data('id');
      $.ajax({
         type : 'POST', 
         url : 'onCheckRadioRmaMain01',
         dataType : 'json',
         data : "idx=" + number,
         success : function(data) {
            var id = data.id;
            var rmaNum = data.rmaNum;
            var rtrnTpCd = data.rtrnTpCd;
            var rtrnRsnCd = data.rtrnRsnCd;
            var sellToCustCd = data.sellToCustCd;
            var rmaHdrStsCd = data.rmaHdrStsCd;
            $("#idId").val(id);
            $("#idRmaNum").val(rmaNum);
            $("div.id_tpCd select").val(rtrnTpCd);
            $("div.id_RsnCd select").val(rtrnRsnCd);
            $("#idSellTo").val(sellToCustCd);
            $("div.id_HdrSts select").val(rmaHdrStsCd);
         },
         error : function(e) {
            alert("error:" +response+ ":" +e);
         }
      });
   });
});

Step 2.4. To the below: text, select box, …. etc

   <tr height="27">
      <td><form:label path="id"><spring:message text="ID"/></form:label></td>
      <td colspan="3">
         <form:input path="id" id="idId" readonly="true" size="8"  disabled="true" style="height:25px; width:200px"/>
         <form:hidden path="id" id="idId" />
      </td> 
   </tr>
   <tr height="27">
      <td><form:label path="rmaNum"><spring:message text="RMA number"/></form:label></td>
      <td colspan="3">
         <form:input path="rmaNum" id="idRmaNum" readonly="true" disabled="true" style="height:25px; width:200px"/>
         <form:hidden path="rmaNum" id="idRmaNum" />
      </td>
   </tr>
   <tr height="27">
      <td><form:label path="rtrnTpCd"><spring:message text="Return Type"/></form:label></td>
      <td>
         <!--<form:select path="rtrnTpCd" items="${TP_LIST}" itemLabel="rtrnTpNm" itemValue="rtrnTpCd" delimiter=" " style="height:20px; width:200px"/>-->
         <div class="id_tpCd">
            <form:select path="rtrnTpCd" id="idSelectTpCd" onchange="onChangeTp();" style="height:25px; width:200px">
               <form:option value="" label="--- Select Type ---"/>
               <form:options items="${TP_LIST}" itemValue="rtrnTpCd" itemLabel="rtrnTpNm"/>
            </form:select>
         </div>
      </td>
      <td><input type="submit" value="Edit Type" name="goToTp" style="height:20px; width:100px"/></td>
      <td><input type="submit" value="Combination" name="goToTpRsn" style="height:22px; width:100px; color: #F6FDA4; background-color: #01690D;"/></td>
   </tr>
   <tr height="27">
      <td><form:label path="rtrnRsnCd"><spring:message text="Return Reason"/></form:label></td>
      <td>
         <!--<form:select path="rtrnRsnCd" items="${RSN_LIST}" itemLabel="rtrnRsnNm" itemValue="rtrnRsnCd" delimiter=" " style="height:20px; width:200px"/>-->
         <div class="id_RsnCd">
         <form:select path="rtrnRsnCd" id="idSelectRsnCd" style="height:25px; width:200px">
            <form:option value="" label="--- Select Reason ---"/>
            <form:options items="${RSN_LIST}" itemValue="rtrnRsnCd" itemLabel="rtrnRsnNm"/>
         </form:select>
         </div>
      </td>
         <td colspan="2">
         <input type="submit" value="Edit Reason" name="goToRsn" style="height:20px; width:100px"/>
      </td>
   </tr>
   <tr height="27">
      <td><form:label path="sellToCustCd"><spring:message text="Costomer Code"/></form:label></td>
      <td colspan="3">
         <form:input path="sellToCustCd" id="idSellTo" style="height:25px; width:200px"/>
      </td>
   </tr>
   <tr height="27">
      <td><form:label path="rmaHdrStsCd"><spring:message text="Header status"/></form:label></td>
      <td colspan="3">
         <div class="id_HdrSts">
            <form:select path="rmaHdrStsCd" items="${HDR_STS_LIST}" id="idSelectStsCd" itemLabel="rmaHdrStsNm" itemValue="rmaHdrStsCd" delimiter=" " style="height:25px; width:200px"/>
         </div>
      </td>
   </tr>

To be continued

Dynamically Creating a Select Box

dropdown-event1
This section is continued from previous section. Select box will be generated as being triggered.
dynamic-combo1

Summarized as three steps:

  1. Javascript function takes two parameters (list of JSON object and ID for select box)
  2. The function clear the select box to be re-constructed
  3. HTML Option tag is created one by one (key and value)

1. Javascript function takes two parameters (list of JSON object and ID for select box)

   $.ajax({
      type : "Get", 
      url : "onChangeTpCdRsnMain01",
      dataType: 'json',
      data : "tpCd=" + tpCd,
      success : function(data) {
         refreshCombo(data, "idSelectRsnCd");
      },
      error : function(e) {
         alert("error:" +response+ ":" +e);
      }
   });

Step 1.1. At line 7, the function call with parameters:

  1. A list of JSON object
  2. [
       Reason Code:001, Name:Item Damaged, Type:02, 
       Reason Code:003, Name:Customer has moved, Type:02, 
       Reason Code:004, Name:Cancelled by customer, Type:02, 
       Reason Code:011, Name:Wrong address, Type:02
    ]
    
  3. ID for a select box
  4. “idSelectRsnCd”


2. The function clear the select box to be re-constructed

function refreshCombo(dataList, comboId) {
   // Remove all current itmes
   $("#"+ comboId).children('option:not(:first)').remove();
   $.each(dataList, function(k, v) {
      // Get each key and value from the list
      var code = v.rtrnRsnCd;
      var val = v.rtrnRsnNm;
      $("#"+ comboId)
         // Set the key and value
         .append($("<option></option>")
         .attr("value",code)
         .text(val)
      );
   });
}

Step 2.1. At line 3, the select box with ID “idSelectRsnCd” is cleared
Step 2.2. At line 6 and 7, inside a loop, get key and value


3. HTML Option tag is created one by one (key and value)

function refreshCombo(dataList, comboId) {
   // Remove all current itmes
   $("#"+ comboId).children('option:not(:first)').remove();
   $.each(dataList, function(k, v) {
      // Get each key and value from the list
      var code = v.rtrnRsnCd;
      var val = v.rtrnRsnNm;
      $("#"+ comboId)
         // Set the key and value
         .append($("<option></option>")
         .attr("value",code)
         .text(val)
      );
   });
}

Step 3.1. At line 10 to 12, inside the loop, constructing HTML by setting the new value and key
Step 3.2. At line 8, the new HTML (with Option tag) is set to the ID “idSelectRsnCd

<form:select path="rtrnRsnCd" id="idSelectRsnCd" style="height:25px; width:200px">
    <form:option value="" label="--- Select Reason ---"/>
    <form:options items="${RSN_LIST}" itemValue="rtrnRsnCd" itemLabel="rtrnRsnNm"/>
</form:select>

Step 3.3. The second select box is re-constructed (ID:idSelectRsnCd)
dynamic-combo2

To Leverage On-Change Dropdown

dropdown-event1
In biz web apps, it is very common that the contents of select box is changed that triggered by other event. Such as select box generated upon other select box selected:
combobox2.2

Summarized as four parts

  1. Javascript (Ajax) is being called as a value is selected
  2. Ajax send a request to the controller method
  3. The controller create a list and send back JSON as a response
  4. Ajax receives the response (JSON) and construct a (second) select box

1. Javascript (Ajax) is being called as a value is selected

2015-05-23_19h54_26
The first select box contains this result (above)

<form:select path="rtrnTpCd" id="idSelectTpCd" onchange="onChangeTp();" style="height:25px; width:200px">
    <form:option value="" label="--- Select Type ---"/>
    <form:options items="${TP_LIST}" itemValue="rtrnTpCd" itemLabel="rtrnTpNm"/>
</form:select>

Step 1.1. As a value is selected, javascript function onChangeTp() is being called selected


2. Ajax send a request to the controller method

function onChangeTp() {
   var tpCd = $('#idSelectTpCd').val();
   $.ajax({
      type : "Get", 
      url : "onChangeTpCdRsnMain01",
      dataType: 'json',
      data : "tpCd=" + tpCd,
      success : function(data) {
         refreshCombo(data, "idSelectRsnCd");
      },
      error : function(e) {
         alert("error:" +response+ ":" +e);
      }
   });
}

Step 2.1. The Ajax send request with parameter to the controller method


3. The controller create a list and send back JSON as a response

@RequestMapping(value = "/onChangeTpCdRsnMain01")
public @ResponseBody List<RtrnRsnModel> refreshRsn(@RequestParam(value = "tpCd") String rtrnTpCd, Model model, HttpServletRequest req) {

	List<RtrnRsnModel> hdrStsList = RsnBL.getRsnsBoundTp(rtrnTpCd);
	model.addAttribute("rtrnTpCd", rtrnTpCd);
	req.getSession().setAttribute(CONST.TP_SELECTED.getVal(), rtrnTpCd);
	return hdrStsList;
}

2015-05-22_07h48_11
Step 3.1. The controller is being called, and following result will be set as result:
2015-05-22_07h34_46
Step 3.2. The controller method send the response (JSON)


4. Ajax receives the response (JSON) and construct a (second) select box

function onChangeTp() {
   var tpCd = $('#idSelectTpCd').val();
   $.ajax({
      type : "Get", 
      url : "onChangeTpCdRsnMain01",
      dataType: 'json',
      data : "tpCd=" + tpCd,
      success : function(data) {
         refreshCombo(data, "idSelectRsnCd");
      },
      error : function(e) {
         alert("error:" +response+ ":" +e);
      }
   });
}

Step 4.1. The Ajax receives a response and pass the result to the Javascript function “refreshCombo

function refreshCombo(dataList, comboId) {
   // Remove all current itmes
   $("#"+ comboId).children('option:not(:first)').remove();
   $.each(dataList, function(k, v) {
      // Get each key and value from the list
      var code = v.rtrnRsnCd;
      var val = v.rtrnRsnNm;
      $("#"+ comboId)
         // Set the key and value
         .append($("<option></option>")
         .attr("value",code)
         .text(val)
      );
   });
}

Step 4.2. At line 3, clear the select box to be re-constructed
Step 4.3. At line 10 to 12, inside the loop, constructing HTML by setting the new value and key
Step 4.4. At line 8, the new HTML (with Option tag) is set to the ID “idSelectRsnCd

<form:select path="rtrnRsnCd" id="idSelectRsnCd" style="height:25px; width:200px">
    <form:option value="" label="--- Select Reason ---"/>
    <form:options items="${RSN_LIST}" itemValue="rtrnRsnCd" itemLabel="rtrnRsnNm"/>
</form:select>

Step 4.5. The second select box is re-constructed (ID:idSelectRsnCd)

Closer detail of the Step 4, see Dynamically Creating a select box

Select Box Stays Selected

mvc-template1
You always see Select Box (Drop down) in Biz Web Apps. Sometimes stand alone, and sometimes in a list.

And Select box usually consists of three values.

    (A) Code that contains a key behind the screen
    (B) Displaying value
    (C) Selected value

stay-selected-img2
(A) and (B) is sometimes together. And you always need (C) in order to the select box stays selected when the page is refreshed.

For example, if you submit a form, without doing anything, the select box will be empty and selected value will be GONE!!!! It will happen every time you refresh a page.


Select box stand alone case:

<form:select path="rtrnTpCd" id="tpCd" onchange="onChangeTp();" style="height:25px; width:200px">
   <form:option value="" label="--- Select Type ---"/>
   <c:forEach items="${TP_LIST}" var="name">
      <c:choose>
         <c:when test="${name.getRtrnTpCd()== TP_SELECTED}">
            <form:option value="${name.getRtrnTpCd()}" selected="true">${name.getRtrnTpNm()}</form:option>
         </c:when>
         <c:otherwise>
            <form:option value="${name.getRtrnTpCd()}">${name.getRtrnTpNm()}</form:option>
         </c:otherwise>
      </c:choose>
   </c:forEach>
</form:select>
@RequestMapping(value = "/onChangeTpCdRsnMain01")
public @ResponseBody List<RtrnRsnModel> refreshRsn(@RequestParam(value = "tpCd") String rtrnTpCd, Model model, HttpServletRequest req) {

	List<RtrnRsnModel> hdrStsList = RsnBL.getRsnsBoundTp(rtrnTpCd);
	model.addAttribute("rtrnTpCd", rtrnTpCd);
	req.getSession().setAttribute(CONST.TP_SELECTED.getVal(), rtrnTpCd);
	return hdrStsList;
}

TP_SELECTED” is being set in the method “refreshRsn” in the Controller class, and the select box is being selected and stays with the value


Select Box in a list:

<c:forEach items="${rmaLineListModel.rmaLineModelList}" var="rmaLnObj" varStatus="i" begin="0">
.
.
.
<c:choose>
	<c:when test="${rmaLnObj.getRmaLineStsCd()== ''}">
		<form:select 
			path="rmaLineModelList[${i.index}].rmaLineStsCd" 
			id="idLnStCd${i.index}" 
			style="height:25px; width:130px">
		<form:option  value="" label=""/>
		<form:options items="${HDR_STS_LIST}" itemValue="rmaHdrStsCd" itemLabel="rmaHdrStsNm"/>
		</form:select>
	</c:when>
	<c:otherwise>
		<form:select 
			path="rmaLineModelList[${i.index}].rmaLineStsCd"
			items="${HDR_STS_LIST}" 
			id="idLnStCd${i.index}"
			itemLabel="rmaHdrStsNm" 
			itemValue="rmaHdrStsCd" 
			delimiter=" " 
			readonly="true" 
			disabled="true" 
			style="height:25px; width:130px"/>
		<form:hidden path="rmaLineModelList[${i.index}].rmaLineStsCd" id="idLnStCd${i.index}" />
	</c:otherwise>
</c:choose>

</c:forEach>

At line 7 to 13, selected value is NOT specified, whereas line 16 to 25 specified.

@RequestMapping("/cUrlValSubLine01Jsp/{rmaNum}")
public ModelAndView goToSubLine01Jsp(@PathVariable("rmaNum") String rmaNum,	Model model, HttpServletRequest req) {
	List<RmaLineModel> rmaLineModelList = RmaDtlBL.getRmaLineListWithCdTblNm(rmaNum, null);
	return getMVSubLine01(rmaNum, rmaLineModelList, req);
}

The controller that create the list of select box.

private ModelAndView getMVSubLine01(String rmaNum, List<RmaLineModel> rmaLinsList, HttpServletRequest req) {

	RmaLineListModel newModel = new RmaLineListModel(rmaNum, rmaLinsList);

	ModelAndView modelAndView = new ModelAndView(VIEW.SUB_LINE_01.getVal());
	modelAndView.addObject(CONST.FORM_KEY.getVal(), newModel);
	// For item detail list
	modelAndView.addObject(CONST.LINE_LIST_MODEL.getVal(), newModel);
	// Setup Status drop down line the item list
	modelAndView.addObject(CONST.HDR_STS_LIST.getVal(), getList(CONST.HDR_STS_LIST.getVal()));
	// Item list for AJAX Auto complete
	req.getSession().setAttribute(CONST.MDSE_LIST.getVal(), getList(CONST.MDSE_LIST.getVal()));
	return modelAndView;
}

The line 10 specify the select box object.