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.

Hash Set vs Array List

title-img-nlogn-1
Recalling a Big-O notation in (CS) Computer Science major course I have taken in College:

O(n)O(1)O(log n)O(n log n)O(n^2)O(n^3)
111111
211248
41281664
8132464512
1614642654096
10241101024010485761073741824

In Biz apps, you need to use List object all the time. And often has performance issue. It’s better to use some other data structure, such as Map object because HashSet is much faster compared to ArrayList:
getcontainsaddremove
ArrayListO(1)O(n)O(1)O(n)
HashSetN/AO(1)O(1)O(1)

Note: HashSet does not provide “get” method, but as long as “contains” method is available, we know what element we need

Here is how to work on:
First, converting ArrayList to HashSet

private Set<String> convertToHashSet(List<Map<String, Object>> listToDelete) {
	Set<String> set = new HashSet<String>();
	for (Map<String, Object> obj : listToDelete) {
		set.add(new String("test"));
	}
	return set;
}

Or just simply set a list as constructor’s parameter:

private Set<String> convertToHashSetDirectory(List<String> list) {
	return new HashSet<String>(list);
}

“contains” with for loop version:

private void hashSetDemoFor(Set<String> setOfMdseOnScreen, Set<String> setOfMdseAcctTo) {
	Map<String, Long> resultMap = new HashMap<String, Long>();
	for (String mdseAcctTo : setOfMdseAcctTo) {
		if (setOfMdseOnScreen.contains(mdseAcctTo)) {
			// Do something
			continue;
		}
	}
}

“contains” with while loop version:

private void hashSetDemoWhile(Set<String> setOfMdseOnScreen, Set<String> setOfMdseAcctTo) {
	Iterator<String> itr = setOfMdseOnScreen.iterator();
	while (itr.hasNext()) {
		String mdseOnScreen = itr.next();
		if (setOfMdseAcctTo.contains(mdseOnScreen)) {
			// Do something
			continue;
		}
	}
}

Generic DAO

db-chain1
For the CRUD operation in Hibernate, you don’t need to repeat Insert, Update, Delete at all. The Generic DAO can take any entity object to do this.

It can be accessed by any entity object with empty method, or some additional customize method

There are Service, and DAO layer, and your controller access Service class
Controller <-> Service <-> DAO : Source Code
model2

The interface of Generic DAO.

package com.ns.spring.dao;

import java.io.Serializable;
import java.util.List;

import com.ns.spring.exception.NSException;

public interface GenHbDao<E, K extends Serializable> {

	public List<E> findAll();	
	public E findById(K key) throws NSException;
	public void save(E obj);
	public void update(E obj);
	public void saveOrUpdate(E obj);
	public void delete(E obj);

}

The implementation of above interface

package com.ns.spring.dao;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

import org.hibernate.ObjectNotFoundException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.ns.spring.exception.NSException;

@SuppressWarnings("unchecked")
@Repository
public abstract class GenHbDaoImpl<E, K extends Serializable> implements GenHbDao<E, K> {

	private SessionFactory sessionFactory;
	private Class<E> clazz;

	public GenHbDaoImpl() {
		Type t = getClass().getGenericSuperclass();
		ParameterizedType pt = (ParameterizedType) t;
		this.clazz = (Class<E>) pt.getActualTypeArguments()[0];
	}

	public Class<E> getCurrClazz() {
		return clazz;
	}

	@Autowired
	public void setSessionFactory(SessionFactory sf) {
		this.sessionFactory = sf;
	}

	protected Session getCurrSession() {
		return sessionFactory.getCurrentSession();
	}

	@Override
	public void save(E obj) {
		this.getCurrSession().persist(obj);
	}

	@Override
	public void update(E obj) {
		this.getCurrSession().update(obj);
	}

	@Override
	public void saveOrUpdate(E obj) {
		this.getCurrSession().saveOrUpdate(obj);
	}

	@Override
	public void delete(E obj) {
		this.getCurrSession().delete(obj);
	}

	@Override
	public List<E> findAll() {
		List<E> list = this.getCurrSession().createCriteria(getCurrClazz()).list();
		return list;
	}

	@Override
	public E findById(K key) throws NSException {
		Session session = this.getCurrSession();
		try {
			E p = (E) session.load(getCurrClazz(), key);
			return p;
		} catch (ObjectNotFoundException e) {
			throw new NSException("No result");
		}
	}
}

The interface of Service class (nearly identical of Generic DAO) that actually called by your controller.

package com.ns.spring.service;

import java.io.Serializable;
import java.util.List;

public interface GenHbService<E, K extends Serializable> {

	public List<E> findAll();
	public E findById(K key);
	public void save(E obj);
	public void update(E obj);
	public void saveOrUpdate(E obj);
	public void delete(E obj);

}

And finally the implementation of the above service interface. Notice the @Transactional annotation in each method

package com.ns.spring.service;

import java.io.Serializable;
import java.util.List;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.ns.spring.dao.GenHbDao;
import com.ns.spring.exception.NSException;

@Service
public abstract class GenHbServiceImpl<E, K extends Serializable> implements GenHbService<E, K> {

	private GenHbDao<E, K> genDao;

	public GenHbServiceImpl(GenHbDao<E, K> genDao) {
		this.genDao = genDao;
	}

	public GenHbServiceImpl() {
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED)
	public void save(E obj) {
		genDao.save(obj);
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED)
	public void update(E obj) {
		genDao.update(obj);
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED)
	public void saveOrUpdate(E obj) {
		genDao.saveOrUpdate(obj);
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED)
	public void delete(E obj) {
		genDao.delete(obj);
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED)
	public List<E> findAll() {
		return genDao.findAll();
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED)
	public E findById(K key) {
		try {
			return genDao.findById(key);
		} catch (NSException e) {
			return null;
		}
	}
}