Saturday, 29 June 2013

ZK MVVM Form Binding CRUD with Spring and Hibernate - Part 12

Validation using Hibernate Validator

        

In the previous article 11, we have completed the part of uploading image file into the database.  In this article, let us see how we can validate user input. There are different ways in ZK Framework to validate the user input, but here i am going to show a different way using JSR 303 Validation.

Before starting, i  would highly recommend to read this post in my blog for better understanding of the validation framework.

Project Structure

image

Step 1:
First we will see which are the mandatory fields in the user creation page and then we will show indication (*) near the fields. The following fields are mandatory as our sql script.

First Name, Last Name, userAccountNumber, address1, city , state, zipcode , email, userloginid, password  and theme.

First in style.css , we will add one more css class for label as shown here

.flblreq.z-label {
font-size: 12px;
font-weight: bolder;
color: red;
}


Open UserCRUD.zul and add the asterisk symbol near by the above fields as show here.

<?page title="" contentType="text/html;charset=UTF-8"?>
<zk>

<window id="userCRUD" border="none"
apply="org.zkoss.bind.BindComposer"
viewModel="@id('vm') @init('zkexample.zkoss.UserCRUDVM')">
<div
form="@id('fx') @load(vm.selectedRecord) @save(vm.selectedRecord, before='saveThis')">

<div width="96%">
<span width="100%">
<div sclass="sectionTitle">
<separator />
<label id="lcaption" sclass="sectionTitleLabel"
value="Add/Edit Users" />
<label id="readonly" sclass="sectionTitleLabel"
value="(ReadOnly)" visible="@load(vm.makeAsReadOnly)" />
<image
src="@load(fxStatus.dirty?'images/unsaved32x32.png':'')" />

</div>
</span>
<div id="buttonsDiv"
style="float:right;margin-top:6px;">
<button label="Save and Close" mold="trendy"
visible="@load(not vm.makeAsReadOnly)"
onClick="@command('saveThis', action=0)"
sclass="mybutton button theme small">
</button>
<button label="Save and Add" mold="trendy"
visible="@load(not vm.makeAsReadOnly)"
onClick="@command('saveThis', action=1)"
sclass="mybutton button theme small">
</button>
<button
label="@load(vm.makeAsReadOnly ?'Close':'Cancel')" mold="trendy"
onClick="@command('cancel')"
sclass="mybutton button theme small">
</button>
</div>
<div style="clear: both;"></div>
<div sclass="sectionSeperator"></div>
</div>

<span width="100%">
<div sclass="sectionTitle">
<separator />
<label value="Personel Information"
sclass="sectionTitleLabel" />
<separator />
</div>
</span>
<div>
<image content="@bind(vm.myImage)" width="150px"
style="overflow:auto;z-index:999;position:absolute;right:30px;top:56px;width:150px;height:140px;background-color:#ff99cc;" />
<button Label="Add" sclass="mybutton button theme small"
width="40px" upload="true,maxsize=300"
visible="@load(not vm.makeAsReadOnly)"
style="position:absolute;right:115px;top:200px;"
onUpload="@command('upload', upEvent=event)" mold="trendy" />
<button Label="Del" sclass="mybutton button theme small"
visible="@load(not vm.makeAsReadOnly)" width="40px"
style="position:absolute;right:30px;top:200px;"
onClick="@command('removeImage')" mold="trendy" />
</div>
<panel width="95%" sclass="sectionPanel">
<panelchildren>
<separator />
<grid sclass="vgrid">
<columns>
<column hflex="10%"></column>
<column hflex="10%"></column>
<column hflex="10%"></column>
<column hflex="10%"></column>
</columns>
<rows>
<row>
<vlayout>
<hlayout>
<label value="User Account No"
sclass="flabel" />
<label value="*"
sclass="flblreq" />
</hlayout>
<textbox id="accountNo"
readonly="@load(vm.makeAsReadOnly)" mold="rounded" hflex="1"
value="@bind(fx.userAccountNumber)" />
</vlayout>
<vlayout>
<hlayout>
<label value="Last Name"
sclass="flabel" />
<label value="*"
sclass="flblreq" />
</hlayout>
<textbox id="lastname"
readonly="@load(vm.makeAsReadOnly)" mold="rounded" hflex="1"
value="@bind(fx.lastName)" />
</vlayout>
<vlayout>
<hlayout>
<label value="First Name"
sclass="flabel" />
<label value="*"
sclass="flblreq" />
</hlayout>
<textbox id="firstname"
readonly="@load(vm.makeAsReadOnly)" mold="rounded" hflex="1"
value="@bind(fx.firstName)" />
</vlayout>
<vlayout>
<label value="Middle Name"
sclass="flabel" />
<textbox id="middleName"
readonly="@load(vm.makeAsReadOnly)" mold="rounded"
value="@bind(fx.middleName)" />
</vlayout>

</row>
<row>

<vlayout>
<hlayout>
<label value="Email"
sclass="flabel" />
<label value="*"
sclass="flblreq" />
</hlayout>
<textbox id="email" hflex="1"
readonly="@load(vm.makeAsReadOnly)" mold="rounded"
value="@bind(fx.email)" />
</vlayout>
<cell colspan="2">
<hbox>
<vlayout>
<label value="SSN"
sclass="flabel" />
<MaskedBox
format="999-99-9999" width="115%"
readonly="@load(vm.makeAsReadOnly)"
value="@bind(fx.SSN) @converter('zkexample.utilities.MaskConverter')">
</MaskedBox>
</vlayout>
<vlayout>
<label value="DOB"
sclass="flabel" />
<MaskedBox
waterMark="mm/dd/yyyy" format="99/99/9999"
readonly="@load(vm.makeAsReadOnly)" width="100%"
value="@bind(fx.DOB) @converter('zkexample.utilities.MyDateFormatConverter')">
</MaskedBox>
</vlayout>
</hbox>
</cell>
</row>
</rows>
</grid>
</panelchildren>
</panel>
<separator />

<separator />
<span width="100%">
<div sclass="sectionTitle">
<separator />
<label value="Address Information"
sclass="sectionTitleLabel" />
<separator />
</div>
</span>
<panel width="95%" sclass="sectionPanel">
<panelchildren>
<grid sclass="vgrid">
<columns>
<column hflex="1"></column>
<column hflex="1"></column>
<column hflex="1"></column>
</columns>
<rows>
<row>
<cell colspan="2">
<vlayout>
<hlayout>
<label value="Address"
sclass="flabel" />
<label value="*"
sclass="flblreq" />
</hlayout>
<textbox id="address1" hflex="2"
readonly="@load(vm.makeAsReadOnly)" mold="rounded"
value="@bind(fx.address1)" />
</vlayout>
</cell>
</row>
<row>
<cell colspan="2">
<vlayout>
<textbox id="address2" hflex="2"
readonly="@load(vm.makeAsReadOnly)" mold="rounded"
value="@bind(fx.address2)" />
</vlayout>
</cell>
</row>
<row>
<vlayout>
<hlayout>
<label value="City"
sclass="flabel" />
<label value="*"
sclass="flblreq" />
</hlayout>
<textbox id="City" hflex="1"
readonly="@load(vm.makeAsReadOnly)" mold="rounded"
value="@bind(fx.city)" />
</vlayout>
<vlayout>
<grid>
<columns>
<column width="60%"></column>
<column></column>
</columns>
<rows>
<row>
<vlayout>
<hlayout>
<label
value="State" sclass="flabel" />
<label value="*"
sclass="flblreq" />
</hlayout>
<textbox id="State"
readonly="@load(vm.makeAsReadOnly)" hflex="1"
mold="rounded" value="@bind(fx.state)" />
</vlayout>
<vlayout>
<hlayout>
<label
value="ZipCode" sclass="flabel" />
<label value="*"
sclass="flblreq" />
</hlayout>
<MaskedBox
format="99999-9999" hflex="1"
readonly="@load(vm.makeAsReadOnly)"
value="@bind(fx.zipCode) @converter('zkexample.utilities.MaskConverter')">
</MaskedBox>

</vlayout>
</row>
</rows>
</grid>
</vlayout>
</row>
</rows>
</grid>
</panelchildren>
</panel>
<separator />
<span width="100%">
<div sclass="sectionTitle">
<separator />
<label value="Login information"
sclass="sectionTitleLabel" />
</div>
</span>
<panel width="95%" sclass="sectionPanel">
<panelchildren>
<separator />
<grid sclass="vgrid">
<columns>
<column width="20%"></column>
<column width="26%"></column>
</columns>
<rows>
<row>
<vlayout>
<hlayout>
<label value="Login ID"
sclass="flabel" />
<label value="*"
sclass="flblreq" />
</hlayout>
<textbox id="loginid" hflex="1"
readonly="@load(vm.makeAsReadOnly)" mold="rounded"
value="@bind(fx.userLoginID)" />
</vlayout>
<vlayout>
<hlayout>
<label value="Password"
sclass="flabel" />
<label value="*"
sclass="flblreq" />
</hlayout>
<textbox id="password" width="80%"
readonly="@load(vm.makeAsReadOnly)" mold="rounded"
value="@bind(fx.password)" />
</vlayout>
<vlayout>
<hlayout>
<label value="Theme"
sclass="flabel" />
<label value="*"
sclass="flblreq" />
</hlayout>
<combobox model="@load(vm.themes)"
width="30%" mold="rounded" readonly="@load(vm.makeAsReadOnly)"
selectedItem="@bind(fx.theme)" value="@bind(fx.theme)" />
</vlayout>
</row>
</rows>
</grid>
</panelchildren>
</panel>
</div>
</window>
</zk>

Now you can see the output as follows
image

Step 2:
Next we will add the Hibernate validator dependency in our POM File.

	<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.3.1.Final</version>
</dependency>

Step 3:
Next we will use hibernate built in constraint @NotBlank to add message to the Not null fields in the UserProfile.java POJO as shown here
 


package zkexample.domain;

import java.io.Serializable;
import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import org.hibernate.annotations.NamedQuery;
import org.hibernate.validator.constraints.NotBlank;

@Entity
@Table(name = "userprofile")
@NamedQuery(name = "UserProfile.findUserByUserID", query = "SELECT usr FROM UserProfile as usr WHERE usr.userLoginID = ?")
public class UserProfile implements Serializable {

/**
*
*/
private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;

@NotBlank(message = "First Name cannot be empty")
private String firstName;

@NotBlank(message = "Last Name cannot be empty")
private String lastName;

private String middleName;

@NotBlank(message = "User Account Number cannot be empty")
private String userAccountNumber;

private String SSN;
@NotBlank(message = "Address1 cannot be empty")
private String address1;

private String address2;

@NotBlank(message = "City cannot be empty")
private String city;

@NotBlank(message = "State cannot be empty")
private String State;

@NotBlank(message = "ZipCode cannot be empty")
private String zipCode;

@NotBlank(message = "Email cannot be empty")
private String email;

@NotBlank(message = "Login Name cannot be empty")
private String userLoginID;

@NotBlank(message = "Password cannot be empty")
private String password;

private Integer system;

@NotBlank(message = "Theme cannot be empty")
private String theme;

@Column(name = "userPhoto")
@Lob
private byte[] userPhoto;

@Temporal(TemporalType.DATE)
private Date DOB;

public long getId() {
return id;
}

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

public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}

public String getMiddleName() {
return middleName;
}

public void setMiddleName(String middleName) {
this.middleName = middleName;
}

public String getUserAccountNumber() {
return userAccountNumber;
}

public void setUserAccountNumber(String userAccountNumber) {
this.userAccountNumber = userAccountNumber;
}

public Date getDOB() {
return DOB;
}

public void setDOB(Date dOB) {
DOB = dOB;
}

public String getSSN() {
return SSN;
}

public void setSSN(String sSN) {
SSN = sSN;
}

public String getAddress1() {
return address1;
}

public void setAddress1(String address1) {
this.address1 = address1;
}

public String getAddress2() {
return address2;
}

public void setAddress2(String address2) {
this.address2 = address2;
}

public String getCity() {
return city;
}

public void setCity(String city) {
this.city = city;
}

public String getState() {
return State;
}

public void setState(String state) {
State = state;
}

public String getZipCode() {
return zipCode;
}

public void setZipCode(String zipCode) {
this.zipCode = zipCode;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

public String getUserLoginID() {
return userLoginID;
}

public void setUserLoginID(String userLoginID) {
this.userLoginID = userLoginID;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public Integer getSystem() {
return system;
}

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

public String getTheme() {
return theme;
}

public void setTheme(String theme) {
this.theme = theme;
}

public byte[] getUserPhoto() {
return userPhoto;
}

public void setUserPhoto(byte[] userPhoto) {
this.userPhoto = userPhoto;
}

}

Step 4:
Next step to show all these validation message in the list box window on click of save in the USERCRUD.ZUL File. For Simple example, please look at this post.

First we will create java class to hold all the validation message. In the package utilities, create the following validationMessage.java class as shown.
package zkexample.utilities;

public class ValidationMessage {
private String message;

public ValidationMessage(String message) {
this.message = message;
}

public ValidationMessage() {
}

public String getMessage() {
return message;
}

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

}

Next we will add our validation message modal window. In the webapp folder, add new zul file called as ValidateWindow.zul
image


<?xml version="1.0" encoding="UTF-8"?>
<zk>
<window id="ValidateWindow" title="Validation" height="auto" width="500px"
border="normal" minimizable="false" mode="modal" maximizable="false"
closable="true" action="hide: slideUp" sclass="mymodal"
apply="org.zkoss.bind.BindComposer" onCancel="@command('closeThis')"
onOK="@command('closeThis')"
viewModel="@id('vm') @init('zkexample.utilities.formValidationVM')">

<listbox vflex="1" sclass="mylist" width="100%" id="test" model="@load(vm.allMessages)">
<listhead sizable="true">
<listheader label="" />
</listhead>
<template name="model" var="p1">
<listitem>
<listcell>
<label value="@load(p1.message)" sclass="flabel" />
</listcell>
</listitem>
</template>
</listbox>
<separator />
<div align="center">
<button label="Close" sclass="mybutton button theme small" mold="trendy" onClick="@command('closeThis')" />
</div>
</window>
</zk>

We will add the VM For the above zul in the package utilities in the name of formValidationVM.java

package zkexample.utilities;
import java.util.List;

import org.zkoss.bind.annotation.AfterCompose;
import org.zkoss.bind.annotation.Command;
import org.zkoss.bind.annotation.ContextParam;
import org.zkoss.bind.annotation.ContextType;
import org.zkoss.bind.annotation.ExecutionArgParam;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.select.Selectors;
import org.zkoss.zk.ui.select.annotation.Wire;
import org.zkoss.zul.Window;

public class formValidationVM {

@Wire("#ValidateWindow")
private Window win;

private List<ValidationMessage> allMessages = null;


public List<ValidationMessage> getAllMessages() {
return allMessages;
}

public void setAllMessages(List<ValidationMessage> allMessages) {
this.allMessages = allMessages;
}

@AfterCompose
public void init(@ContextParam(ContextType.VIEW) Component view,@ExecutionArgParam("vList") List<ValidationMessage> vList) {
Selectors.wireComponents(view, this, false);
setAllMessages(vList);
}

@Command
public void closeThis() {
win.detach();
}
}

Step 5:
Next we will add our validation routine to validate the any hibernate POJO Class. In the utilities package, add the following java class

image

ValidatorUtil.java


package zkexample.utilities;

import java.util.HashSet;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import javax.validation.groups.Default;

public class ValidatorUtil {

private final ValidatorFactory factory;

public ValidatorUtil() {
factory = Validation.buildDefaultValidatorFactory();
}

public <T> HashSet<ConstraintViolation<?>> validate(final T instance) {
final Validator validator = factory.getValidator();

final Set<ConstraintViolation<T>> violations = validator.validate(
instance, Default.class);

if (!violations.isEmpty()) {
final Set<ConstraintViolation<?>> constraints = new HashSet<ConstraintViolation<?>>(
violations.size());

for (final ConstraintViolation<?> violation : violations) {
constraints.add(violation);
}

return (HashSet<ConstraintViolation<?>>) constraints;
}
return null;
}

}


Add the following method in MyLib.java  to validate any hibernate POJO Class

public static <T> boolean IsValidBean(final T instance) {

List<ValidationMessage> vList = new ArrayList<ValidationMessage>();

final Set<ConstraintViolation<?>> constraints = new ValidatorUtil()
.validate(instance);
if (constraints == null) {
return true;
}
for (final ConstraintViolation<?> violation : constraints) {
vList.add(new ValidationMessage(violation.getMessage()));
}
if (vList.size() > 0) {
final HashMap<String, Object> map = new HashMap<String, Object>();
map.put("vList", vList);
Executions.createComponents("ValidateWindow.zul",
null, map);
return false;
} else
return true;
}

Step 6:
Finally, we will call the validator routine in the saveThis Method of UserCRUDVM.java


	@Command
public void saveThis(@BindingParam("action") Integer action) {

if (MyLib.IsValidBean(this.selectedRecord) == false) {
return;
}

if (myImage != null) {
byte[] bFile = myImage.getByteData();
this.selectedRecord.setUserPhoto(bFile);
} else
this.selectedRecord.setUserPhoto(null);
CRUDService.Save(this.selectedRecord);
MyLib.showSuccessmessage();
if (action == 0) {
final HashMap<String, Object> map = new HashMap<String, Object>();
map.put("centerArea", centerArea);
centerArea.getChildren().clear();
Executions.createComponents("userList.zul", centerArea, map);
}
if (action == 1) {
this.selectedRecord = new UserProfile();
BindUtils.postNotifyChange(null, null, UserCRUDVM.this,
"selectedRecord");

}
}


Now run the application and click Add New Button and just Click either “Save and Close” or “Save and Add”. You can see all the validation message as shown

image
In the Next part 13, we will see how we can add more constraints and also how we can create our constraints.

You can download the source here.
Don’t forget to check online demo here. Use username as wing and password as wing

        

Wednesday, 19 June 2013

EDI 270–5010 Documentation– Loop 2100C SUBSCRIBER Name

2100C Subscriber Name

        


Use this segment to identify an entity by name and/or identification number. Use this NM1 loop to identify the insured or subscriber

 
Loop Seg ID Segment Name Format Length Ref# Req Value
2100C NM1 Subscriber Name ID 3 R NM1
Element Separator AN 1 *
NM101 Entity Identifier Code ID 2/3 98 R IL
Element Separator AN 1 *
NM102 Entity Type qualifier ID 1/1 1065 R 1
Element Separator AN 1 *
NM103 Name Last or Organization Name AN 1/60 1035 R Insured Person Last Name
Element Separator AN 1 *
NM104 Name First AN 1/35 1036 S Insured Person First Name
Element Separator AN 1 *
NM105 Name Middle AN 1/25 1037 S Insured Person Middle Name
Element Separator AN 1 *
NM106 Name Prefix AN 1/10 1038 Not used
Element Separator AN 1 *
NM107 Name Suffix AN 1/10 1039 S Insured Person Suffix
Element Separator AN 1 *
NM108 Identification code Qualifier ID 1/2 66 R MI
Element Separator AN 1 *
NM109 Identification code AN 2/80 67 R Insured Policy No
Segment Terminator ~
               
 
 
NM102 - Entity Type Qualifier
Code qualifying the type of entity
Code Definition
1 Person
2 Non-Person Entity

 
Sample
NM1*IL*1*MULLIN*DANIEL****MI*XJBH12345678~

Segment Structure
image


image




SUBSCRIBER DEMOGRAPHIC INFORMATION

Use this segment to convey the birth date or gender demographic information for the subscriber. Use this segment only if the subscriber is the patient and if this information is available from the Information Source’s database.

Loop Seg ID Segment Name Format Length Ref# Req Value
2100C DMG Demographic Information ID 3 S DMG
Element Separator AN 1 *
DMG01 Date Time Period format Qualifier ID 2 1250 S D8 = Date format
Element Separator AN 1 *
DMG02 Date Time Period AN 8 1251 S <CCYYMMDD - Recipient Date of Birth>
Segment Terminator     ~


Sample
DMG*D8*19571112

image

 

 
In the PMS Software, you can fetch the information from Patient Insurance Insurer details as shown here

image


SUBSCRIBER VISIT DATE

Loop Seg ID Segment Name Format Length Ref# Req Value
2100C DTP Subscriber Date ID 3 S DMG
Element Separator AN 1 *
DTP01 Date Time Qualifier ID 3 374 R 291=Plan
Element Separator AN 1 *
DTP02 Date Time Period Format Qualifier ID 3 1250 R RD8=Date Format
    Element Separator AN 1      
  DTP03 Date Time Period AN 17 1251 R <CCYYMMDD - Recipient Date of Service>
Always Current Date
Segment Terminator     ~

 
Sample
DTP*291*D8*20130829

image

        
 
 
Questions or feedback are always welcome. You can email me at vbsenthilinnet@gmail.com

Monday, 17 June 2013

EDI 270–5010 Documentation– 2000C SUBSCRIBER LEVEL

SUBSCRIBER TRACE NUMBER

Trace numbers assigned at the subscriber level are intended to allow tracing of an eligibility/benefit transaction when the subscriber is the patient. The information receiver may assign one TRN segment in this loop if the subscriber is the patient. A clearinghouse may assign one TRN segment in this loop if the subscriber is the patient

Loop Seg ID Segment Name Format Length Ref# Req Value
Header TRN Subscriber Trace Number ID 3 R TRN
Element Separator AN 1 *
TRN01 Trace Type Code ID 1 481 R 1 = Current Transaction Trace Number
Element Separator AN 1 *
TRN02 Reference Identification AN 1/50 127 R <Trace Number: Assigned by information receiver or information receiver’s clearing house>
Element Separator AN 1 *
TRN03 Originating Company Identifier AN 10 509 R <ID Number of the company that assigned the trace number>
Segment Terminator ~
               
 
Sample

TRN*1*290811021*3030240928~

Segment Structure
image

image

        
 
 
Questions or feedback are always welcome. You can email me at vbsenthilinnet@gmail.com