0

I want to edit my row in a datatable, but I have a problem. I have a validator which checks whether there is a social security number in the database. When I add everything is ok. The problem occurs when I'm editing. Below is the code fragment from my edit page:

<h:form>
    <div id="userPanel">
        <p:panel id="panelUser" header="Edytuj administratora" >
            <div id="panelImage">
                <img src="./../../images/person4.png" alt="person" width="150px" height="130px"/>
            </div>
            <h:inputHidden value="#{userMB.user.id}" />
            <h:panelGrid columns="3">
                <p:outputLabel for="firstName" value="#{msg.firstName}"></p:outputLabel>
                <p:inputText id="firstName" value="#{userMB.user.firstName}" label="#{msg.firstName}" required="true">
                    <f:validator validatorId="firstNameValidator" />  
                    <p:ajax update="msgFristName" event="keyup" />  
                </p:inputText>  
                <p:message for="firstName" id="msgFristName"/> 

                <p:outputLabel for="lastName" value="#{msg.lastName}"></p:outputLabel>
                <p:inputText id="lastName" value="#{userMB.user.lastName}" label="#{msg.lastName}" required="true">
                    <f:validator validatorId="lastNameValidator" />   
                    <p:ajax update="msgLastName" event="keyup" /> 
                </p:inputText>  
                <p:message for="lastName" id="msgLastName"/> 

                <p:outputLabel for="personalId" value="#{msg.personalId}"></p:outputLabel>
                <p:inputText id="personalId" value="#{userMB.user.personalId}" label="#{msg.personalId}" required="true">
                    <f:validator binding="#{personalIdValidator}" />   
                    <p:ajax update="msgPersonalId" event="keyup" /> 
                </p:inputText>  
                <p:message for="personalId" id="msgPersonalId"/>

                <p:outputLabel for="password" value="#{msg.password}"></p:outputLabel>
                <p:inputText id="password" value="#{userMB.user.password}" label="#{msg.password}" required="true">
                    <f:validator validatorId="passwordValidator" />   
                    <f:attribute name="confirmPassword" value="#{confirmPassword}" />
                    <p:ajax update="msgPassword" event="keyup" /> 
                </p:inputText>  
                <p:message for="password" id="msgPassword"/>

                <p:outputLabel for="confirmPassword" value="#{msg.confirmPassword}"></p:outputLabel>
                <p:inputText id="confirmPassword" binding="#{confirmPassword}" label="#{msg.confirmPassword}" required="true">
                    <f:validator validatorId="passwordValidator" />   
                    <f:attribute name="confirmPassword" value="#{confirmPassword}" />
                    <p:ajax update="msgConfirmPassword" event="keyup" /> 
                </p:inputText>  
                <p:message for="confirmPassword" id="msgConfirmPassword"/>
            </h:panelGrid>
            <center><p:commandButton value="#{msg.edit}" action="#{userMB.editUser()}" ajax="false">
                    <f:param name="userRole" value="admin" />
                    <f:param name="active" value="true" />
                </p:commandButton>
                <p:commandButton value="#{msg.cancel}" action="#{userMB.cancel()}" ajax="false" immediate="true"/></center>
        </p:panel>
    </div>
</h:form>

When I want to edit a user I click the button:

<center><p:commandButton value="#{msg.edit}" action="#{userMB.editUser()}" ajax="false">

which calls the method editUser:

public String editUser() {
    FacesContext context = FacesContext.getCurrentInstance();
    Map requestParameterMap = (Map) context.getExternalContext().getRequestParameterMap();
    try {
        String userRole = requestParameterMap.get("userRole").toString();
        String active = requestParameterMap.get("active").toString();
        Boolean act = Boolean.parseBoolean(active);
        user.setRole(userRole);
        user.setActive(act);
        if ((user.getEmail() != null) && (userDao.findEmailExist(user.getEmail()))) {
            sendErrorMessageToUser("Użytkownik z podanym adresem email istnieje w bazie");
            return null;
        } else if ((user.getPersonalId() != null) && (userDao.findPersonalIdExist(user.getPersonalId()))) {
            sendErrorMessageToUser("Użytkownik z podanym numerem pesel istnieje w bazie");
            return null;
        } else if ((user.getPhone() != null) && (userDao.findPhoneExist(user.getPhone()))) {
            sendErrorMessageToUser("Użytkownik z podanym numerem telefonu istnieje w bazie");
            return null;
        } else {
            userDao.update(user);
        }
    } catch (EJBException e) {
        sendErrorMessageToUser("Błąd edycji użytkownika w bazie");
        return null;
    }
    sendInfoMessageToUser("Konto zedytowane");
    return user.getRole() + "List";
}

Method find personalIdExist returns true when it finds the personalId given during the editing, if it is not found it returns false.

And this is my problem. When I am editing User my edit page looks this: Example:

firstName: Pablo

lastName: ABCD

personalId: 12345678901

password: zxcv

When I am editing my personalId everything is ok, but I can only edit firstName, lastName and password not personalId. PersonalId may be the same. When I click edit I have a problem, because my method personalIdExist returns true if the id already exists and I can't update my user. I need somewhere to save the initial value personalId this user to be able to edit it. But do not know how.

Andy
  • 5,900
  • 2
  • 20
  • 29
The Nightmare
  • 701
  • 5
  • 16
  • 36

2 Answers2

2

As I understand it, checking if you have a repeated id in the database is part of the persistence layer and you should not try to verify it in the Validator.

Use the validator to check more formal issues (format of the data, required data missing, etc.). The issue of duplicated id should be controlled either by bussiness logic or be delegated to the persistence layer; there it will be no problem because you will know if the operation is adding a new user or modifying an existing one.

If you insist in using a validator for this, create an specific validator for each issue (updating a personal or creating a personal)

UPDATE: I think I see what you want. You want that after each character added to the id, it gets verified against the database if it already exists or not, and a message shown if it already exists, isn't it? But sometimes that check should be an error (because it introduces a duplicate), while at others it should not (because it is looking up for a number). Am I right?

In that case, I would say that you have two different usages and you should use two different properties (newPersonalId and editedPersonalId), and not try to mix them.

Another approach could be creating a exists boolean property in your bean; setting personalId would cause a lookup to proceed and, if already in the database, the exists property would be set to true. In the XHTML, some elements would be rendered/disabled based on this; but that would be too complicated for my taste.

UPDATE2: I still do not understand it, you are actively preventing updating the database if the user already exists, with this code

    } else if ((user.getPersonalId() != null) && (userDao.findPersonalIdExist(user.getPersonalId()))) {
        sendErrorMessageToUser("Użytkownik z podanym numerem pesel istnieje w bazie");
        return null;

The persistence layer is pretty simple, just remember that at this stage user is a Detached Entity so you need to use EntityManager.merge method.

SJuan76
  • 24,532
  • 6
  • 47
  • 87
  • Ok, thanks. I move it to buissness logic. But this does not solve my problem of personalId for editing. I need somewhere to save the initial value personalId to exluce it for checking reps in database. – The Nightmare Jun 29 '13 at 16:22
  • But (unless I did not understand your pa that will be done with a `` or similar that calls an action method. Call a different action for editing an existing row or saving a new one. Otherwise, I would need more context of the command components and your action methods to provide more advice. – SJuan76 Jun 29 '13 at 16:43
  • I think the problem he is having is when he tries to update anything aside from the personalId it will give him an error. – Andy Jun 29 '13 at 21:31
  • Additional tip: If you edit, do not make your id field editable. That can only lead to trouble. Make it hidden and, if you feel like the end user should see it, print it somewhere (but keep the hidden field) – SJuan76 Jun 29 '13 at 21:33
1

This is my interpretation of your problem.

When you edit a user by changing everything BUT the personalId you get an error

SJuan76 approach is the correct one. You don't want to make the validator do that check for you. Instead, just focus on making sure that the user enters a value for the personlId like you expect. Then, make the persistence layer enforce the uniqueness for you (there's no need to write your own logic). I'm assuming you are using an ORM (but I'm not sure which one) so your UserMB should look something like this (pseudo code as I'm writing off the top of my head).

public class UserMB {

    private Long personalId; //Not sure what your actual type is 

    @Column(unique = true)//Uniqueness constraint
    public Long getPersonalId() { 
        return personalId; 
    }

    //Remainder omitted
}

If you are using plain SQL or some variant then make sure you declare that uniqueness constraint for your personalId column when you create your table. In both cases, when you try to update your UserMB personalId and someone else already has it an exception will be thrown. Simply catch it and return it as an error message.

With this change you will no longer need the following method in your codition

findPersonalIdExist(user.getPersonalId())

(which by the way is the root cause of your problem) what's going to happen is if you try to update firstName, lastName without changing personalId everything will run smoothly. If you try to edit your personal id and someone else has it already then the update will not be allowed.

COMMENT

This is unrelated to your concrete problem but I'm a little concerned with your logic. You already have the user id below (which I'm guessing is the one your ORM is managing).

<h:inputHidden value="#{userMB.user.id}" />

Therefore you should not try to find if a column (e.g. phoneNumber) exist by passing the value as an argument. You should grab a user instance directly based on his unique id from the DB and verify is he is not just re entering the same information. You might run into problems. Here's a scenario:

userA wants to change phone number from 123 to 345

userB already has phone number 345

Your code will return true even though user A is not entering the same value (unless that's what you want). If you do want everyone to have unique values for their fields simply add unique="true" where it is needed. No need for all these checks.

You can also eliminate all the null checks by supplying your own converter or setting some parameters in faces-config so that all submitted empty strings will be interpreted as null. Please see the link below

h:inputText which is bound to String property is submitting empty string instead of null

Community
  • 1
  • 1
Andy
  • 5,900
  • 2
  • 20
  • 29