]> git.mxchange.org Git - jfinancials-war.git/commitdiff
Continued with adding user by administrator:
authorRoland Haeder <roland@mxchange.org>
Tue, 12 Apr 2016 16:58:39 +0000 (18:58 +0200)
committerRoland Haeder <roland@mxchange.org>
Tue, 12 Apr 2016 17:21:56 +0000 (19:21 +0200)
- added addUser() method
- removed creation timestamp as the EJB takes care of it
- renamed errorHandler -> exception as this will become a page for thrown exceptions (later better handling)
- updated jar(s)

Signed-off-by: Roland Häder <roland@mxchange.org>
nbproject/faces-config.NavData
src/java/org/mxchange/addressbook/beans/user/AddressbookAdminUserWebSessionBean.java
src/java/org/mxchange/addressbook/beans/user/AddressbookAdminUserWebSessionController.java
src/java/org/mxchange/addressbook/beans/user/AddressbookUserWebSessionBean.java
src/java/org/mxchange/addressbook/beans/user/AddressbookUserWebSessionController.java
src/java/org/mxchange/addressbook/converter/country/AddressbookCountryConverter.java
src/java/org/mxchange/addressbook/converter/smsprovider/AddressbookSmsProviderConverter.java
web/WEB-INF/faces-config.xml
web/exception.xhtml [new file with mode: 0644]

index a2fa258790e846dbdcab823b905a8ab7288c8ef9..8e9c103d878c24b1ff82826dab99d16307539396 100644 (file)
@@ -2,46 +2,46 @@
 <Scene Scope="Project" version="2">
     <Scope Scope="Faces Configuration Only"/>
     <Scope Scope="Project">
-        <Node id="login/login_shared_addressbooks.xhtml" x="1150" y="150" zoom="true"/>
-        <Node id="admin/admin_country_list.xhtml" x="1650" y="300" zoom="true"/>
-        <Node id="admin/admin_user_delete.xhtml" x="400" y="750" zoom="true"/>
-        <Node id="login/login_change_password.xhtml" x="1400" y="300" zoom="true"/>
-        <Node id="privacy.xhtml" x="1150" y="600" zoom="true"/>
-        <Node id="admin/index.xhtml" x="900" y="150" zoom="true"/>
-        <Node id="basket.xhtml" x="900" y="750" zoom="true"/>
-        <Node id="login/login_data_saved.xhtml" x="1400" y="600" zoom="true"/>
-        <Node id="admin/admin_country_delete.xhtml" x="400" y="150" zoom="true"/>
-        <Node id="login/login_start_sharing_addressbook.xhtml" x="650" y="750" zoom="true"/>
-        <Node id="user/register.xhtml" x="400" y="450" zoom="true"/>
-        <Node id="admin/admin_country_edit.xhtml" x="150" y="750" zoom="true"/>
-        <Node id="user/resend_link.xhtml" x="150" y="450" zoom="true"/>
-        <Node id="login/login_index.xhtml" x="400" y="900" zoom="true"/>
-        <Node id="login/login_add_addressbook.xhtml" x="150" y="1050" zoom="true"/>
-        <Node id="login/login_own_addressbooks.xhtml" x="650" y="450" zoom="true"/>
-        <Node id="admin/admin_user_list.xhtml" x="400" y="600" zoom="true"/>
-        <Node id="admin/admin_logout.xhtml" x="400" y="300" zoom="true"/>
-        <Node id="terms.xhtml" x="1650" y="150" zoom="true"/>
-        <Node id="admin/admin_user_add.xhtml" x="900" y="600" zoom="true"/>
-        <Node id="admin/admin_user_edit.xhtml" x="1900" y="300" zoom="true"/>
-        <Node id="user/user_list.xhtml" x="900" y="300" zoom="true"/>
-        <Node id="errorHandler.xhtml" x="650" y="150" zoom="true"/>
-        <Node id="index.xhtml" x="650" y="300" zoom="true"/>
-        <Node id="logout.xhtml" x="1650" y="450" zoom="true"/>
-        <Node id="user/register_done.xhtml" x="1900" y="150" zoom="true"/>
-        <Node id="login/login_change_personal_data.xhtml" x="150" y="300" zoom="true"/>
-        <Node id="user/user_profile.xhtml" x="1400" y="150" zoom="true"/>
-        <Node id="admin/admin_user_unlock.xhtml" x="650" y="900" zoom="true"/>
-        <Node id="imprint.xhtml" x="150" y="900" zoom="true"/>
-        <Node id="user/show_addressbook.xhtml" x="400" y="1050" zoom="true"/>
-        <Node id="*" x="150" y="1200" zoom="true"/>
-        <Node id="user/login_error.xhtml" x="650" y="600" zoom="true"/>
-        <Node id="login/login_other_addressbooks.xhtml" x="1150" y="300" zoom="true"/>
-        <Node id="user/show_addressbook_entries.xhtml" x="900" y="450" zoom="true"/>
-        <Node id="login/login_change_email_address.xhtml" x="1400" y="450" zoom="true"/>
-        <Node id="user/lost_passwd.xhtml" x="150" y="600" zoom="true"/>
-        <Node id="user/login.xhtml" x="1150" y="450" zoom="true"/>
-        <Node id="login/login_list_sharing_addressbooks.xhtml" x="2150" y="150" zoom="true"/>
-        <Node id="login/login_edit_user_data.xhtml" x="150" y="150" zoom="true"/>
+        <Node id="login/login_shared_addressbooks.xhtml" x="1048" y="32" zoom="true"/>
+        <Node id="admin/admin_country_list.xhtml" x="7861" y="32" zoom="true"/>
+        <Node id="admin/admin_user_delete.xhtml" x="2763" y="32" zoom="true"/>
+        <Node id="privacy.xhtml" x="3409" y="32" zoom="true"/>
+        <Node id="login/login_change_password.xhtml" x="7439" y="32" zoom="true"/>
+        <Node id="admin/index.xhtml" x="10625" y="32" zoom="true"/>
+        <Node id="basket.xhtml" x="785" y="32" zoom="true"/>
+        <Node id="login/login_data_saved.xhtml" x="4684" y="32" zoom="true"/>
+        <Node id="exception.xhtml" x="5059" y="32" zoom="true"/>
+        <Node id="admin/admin_country_delete.xhtml" x="13542" y="32" zoom="true"/>
+        <Node id="login/login_start_sharing_addressbook.xhtml" x="8253" y="32" zoom="true"/>
+        <Node id="user/register.xhtml" x="3933" y="32" zoom="true"/>
+        <Node id="admin/admin_country_edit.xhtml" x="5342" y="32" zoom="true"/>
+        <Node id="user/resend_link.xhtml" x="7108" y="32" zoom="true"/>
+        <Node id="login/login_add_addressbook.xhtml" x="9941" y="32" zoom="true"/>
+        <Node id="login/login_index.xhtml" x="12549" y="32" zoom="true"/>
+        <Node id="login/login_own_addressbooks.xhtml" x="9510" y="32" zoom="true"/>
+        <Node id="admin/admin_user_list.xhtml" x="9140" y="32" zoom="true"/>
+        <Node id="terms.xhtml" x="6399" y="32" zoom="true"/>
+        <Node id="admin/admin_logout.xhtml" x="11116" y="32" zoom="true"/>
+        <Node id="admin/admin_user_add.xhtml" x="34" y="32" zoom="true"/>
+        <Node id="admin/admin_user_edit.xhtml" x="409" y="32" zoom="true"/>
+        <Node id="user/user_list.xhtml" x="5740" y="32" zoom="true"/>
+        <Node id="index.xhtml" x="3157" y="32" zoom="true"/>
+        <Node id="logout.xhtml" x="3673" y="32" zoom="true"/>
+        <Node id="user/register_done.xhtml" x="6050" y="32" zoom="true"/>
+        <Node id="user/user_profile.xhtml" x="13208" y="32" zoom="true"/>
+        <Node id="login/login_change_personal_data.xhtml" x="11472" y="32" zoom="true"/>
+        <Node id="admin/admin_user_unlock.xhtml" x="1982" y="32" zoom="true"/>
+        <Node id="user/show_addressbook.xhtml" x="2376" y="32" zoom="true"/>
+        <Node id="imprint.xhtml" x="10361" y="32" zoom="true"/>
+        <Node id="*" x="10924" y="32" zoom="true"/>
+        <Node id="user/login_error.xhtml" x="12881" y="32" zoom="true"/>
+        <Node id="login/login_other_addressbooks.xhtml" x="13958" y="32" zoom="true"/>
+        <Node id="user/show_addressbook_entries.xhtml" x="4240" y="32" zoom="true"/>
+        <Node id="login/login_change_email_address.xhtml" x="6654" y="32" zoom="true"/>
+        <Node id="user/lost_passwd.xhtml" x="11926" y="32" zoom="true"/>
+        <Node id="login/login_list_sharing_addressbooks.xhtml" x="1499" y="32" zoom="true"/>
+        <Node id="user/login.xhtml" x="12264" y="32" zoom="true"/>
+        <Node id="login/login_edit_user_data.xhtml" x="8741" y="32" zoom="true"/>
     </Scope>
     <Scope Scope="All Faces Configurations"/>
 </Scene>
index 229d4bf9f580d722a2dd47229856578d42b0bc5a..8a6b701d5d8d792de493b488536dec3a5edebb65 100644 (file)
@@ -24,16 +24,30 @@ import java.util.Objects;
 import javax.annotation.PostConstruct;
 import javax.enterprise.context.SessionScoped;
 import javax.faces.view.facelets.FaceletException;
+import javax.inject.Inject;
 import javax.inject.Named;
 import javax.naming.Context;
 import javax.naming.InitialContext;
 import javax.naming.NamingException;
+import org.mxchange.jcontacts.contact.Contact;
+import org.mxchange.jcontacts.contact.UserContact;
 import org.mxchange.jcontacts.contact.gender.Gender;
 import org.mxchange.jcountry.data.Country;
+import org.mxchange.jphone.phonenumbers.cellphone.CellphoneNumber;
+import org.mxchange.jphone.phonenumbers.cellphone.DialableCellphoneNumber;
+import org.mxchange.jphone.phonenumbers.fax.DialableFaxNumber;
+import org.mxchange.jphone.phonenumbers.fax.FaxNumber;
+import org.mxchange.jphone.phonenumbers.landline.DialableLandLineNumber;
+import org.mxchange.jphone.phonenumbers.landline.LandLineNumber;
 import org.mxchange.jphone.phonenumbers.smsprovider.SmsProvider;
+import org.mxchange.jusercore.exceptions.EmailAddressAlreadyRegisteredException;
+import org.mxchange.jusercore.exceptions.UserNameAlreadyRegisteredException;
 import org.mxchange.jusercore.exceptions.UserNotFoundException;
+import org.mxchange.jusercore.exceptions.UserPasswordMismatchException;
+import org.mxchange.jusercore.model.user.LoginUser;
 import org.mxchange.jusercore.model.user.User;
 import org.mxchange.jusercore.model.user.UserSessionBeanRemote;
+import org.mxchange.jusercore.model.user.UserUtils;
 import org.mxchange.jusercore.model.user.profilemodes.ProfileMode;
 
 /**
@@ -181,6 +195,12 @@ public class AddressbookAdminUserWebSessionBean implements AddressbookAdminUserW
         */
        private Integer zipCode;
 
+       /**
+        * Regular user controller
+        */
+       @Inject
+       private AddressbookUserWebSessionController userController;
+
        /**
         * Default constructor
         */
@@ -201,6 +221,128 @@ public class AddressbookAdminUserWebSessionBean implements AddressbookAdminUserW
                }
        }
 
+       @Override
+       public void addUser () {
+               // Create new user instance
+               User user = new LoginUser();
+               user.setUserName(this.getUserName());
+               user.setUserProfileMode(this.getUserProfileMode());
+
+               // Generate phone number
+               DialableLandLineNumber phone = new LandLineNumber(this.getPhoneCountry(), this.getPhoneAreaCode(), this.getPhoneNumber());
+               DialableCellphoneNumber cellphone = new CellphoneNumber(this.getCellphoneCarrier(), this.getCellphoneNumber());
+               DialableFaxNumber fax = new FaxNumber(this.getFaxCountry(), this.getFaxAreaCode(), this.getFaxNumber());
+
+               // Create new contact
+               Contact contact = new UserContact(this.getGender(), this.getFirstName(), this.getFamilyName());
+               contact.setContactStreet(this.getStreet());
+               contact.setContactHouseNumber(this.getHouseNumber());
+               contact.setContactZipCode(this.getZipCode());
+               contact.setContactCity(this.getCity());
+               contact.setContactCountry(this.getCountry());
+               contact.setContactEmailAddress(this.getEmailAddress());
+
+               // Don't set null or wrong references
+               if ((phone instanceof DialableLandLineNumber) && (phone.getPhoneCountry() instanceof Country) && (this.getPhoneAreaCode() != null) && (this.getPhoneNumber() != null) && (this.getPhoneAreaCode() > 0) && (this.getPhoneNumber() > 0)) {
+                       // Now the number must be given
+                       if (phone.getPhoneAreaCode() == null) {
+                               // Is null
+                               throw new NullPointerException("phone.phoneAreaCode is null"); //NOI18N
+                       } else if (phone.getPhoneAreaCode() < 1) {
+                               // Abort here
+                               throw new IllegalArgumentException("phone.phoneAreaCode is zero or below."); //NOI18N
+                       } else if (phone.getPhoneNumber() == null) {
+                               // Is null
+                               throw new NullPointerException("phone.phoneNumber is null"); //NOI18N
+                       } else if (phone.getPhoneNumber() < 1) {
+                               // Abort here
+                               throw new IllegalArgumentException("phone.phoneNumber is zero or below."); //NOI18N
+                       }
+
+                       // Set phone number
+                       contact.setContactLandLineNumber(phone);
+               }
+
+               // Don't set null or wrong references
+               if ((fax instanceof DialableFaxNumber) && (fax.getPhoneCountry() instanceof Country) && (this.getFaxAreaCode() != null) && (this.getFaxNumber() != null) && (this.getFaxAreaCode() > 0) && (this.getFaxNumber() > 0)) {
+                       // Now the number must be given
+                       if (fax.getPhoneAreaCode() == null) {
+                               // Is null
+                               throw new NullPointerException("fax.phoneAreaCode is null"); //NOI18N
+                       } else if (fax.getPhoneAreaCode() < 1) {
+                               // Abort here
+                               throw new IllegalArgumentException("fax.phoneAreaCode is zero or below."); //NOI18N
+                       } else if (fax.getPhoneNumber() == null) {
+                               // Is null
+                               throw new NullPointerException("fax.phoneNumber is null"); //NOI18N
+                       } else if (fax.getPhoneNumber() < 1) {
+                               // Abort here
+                               throw new IllegalArgumentException("fax.phoneNumber is zero or below."); //NOI18N
+                       }
+
+                       // Set fax number
+                       contact.setContactFaxNumber(fax);
+               }
+
+               // Is the provider set?
+               if ((cellphone instanceof DialableCellphoneNumber) && (this.getCellphoneCarrier() instanceof SmsProvider) && (this.getCellphoneNumber() != null) && (this.getCellphoneNumber() > 0)) {
+                       // Is the number set?
+                       if (cellphone.getPhoneNumber() == null) {
+                               // Is null
+                               throw new NullPointerException("cellphone.phoneNumber is null"); //NOI18N
+                       } else if (cellphone.getPhoneNumber() < 1) {
+                               // Abort here
+                               throw new IllegalArgumentException("cellphone.phoneNumber is zero or below."); //NOI18N
+                       }
+
+                       // Set cellphone number
+                       contact.setContactCellphoneNumber(cellphone);
+               }
+
+               contact.setContactBirthday(this.getBirthday());
+               contact.setContactComment(this.getComment());
+
+               // Set contact in user
+               user.setUserContact(contact);
+
+               // Init variable for password
+               String password = null;
+
+               // Is the user name or email address used already?
+               // @TODO Add password length check
+               if (this.userController.isUserNameRegistered(user)) {
+                       // User name is already used
+                       throw new FaceletException(new UserNameAlreadyRegisteredException(user));
+               } else if (this.userController.isEmailAddressRegistered(user)) {
+                       // Email address is already used
+                       throw new FaceletException(new EmailAddressAlreadyRegisteredException(user));
+               } else if ((this.getUserPassword().isEmpty()) && (this.getUserPasswordRepeat().isEmpty())) {
+                       // Empty password entered, then generate one
+                       password = UserUtils.createRandomPassword(AddressbookUserWebSessionController.MINIMUM_PASSWORD_LENGTH);
+               } else if (!this.isSamePasswordEntered()) {
+                       // Both passwords don't match
+                       throw new FaceletException(new UserPasswordMismatchException(user));
+               } else {
+                       // Both match, so get it from this bean
+                       password = this.getUserPassword();
+               }
+
+               // The password should not be null and at least 5 characters long
+               assert (password != null) : "password is null";
+               assert (password.length() >= AddressbookUserWebSessionController.MINIMUM_PASSWORD_LENGTH) : "Password is not long enough.";
+
+               // Encrypt password and set it
+               user.setUserEncryptedPassword(UserUtils.encryptPassword(password));
+
+               try {
+                       // Now, that all is set, call EJB
+                       this.userBean.addUser(user);
+               } catch (final UserNameAlreadyRegisteredException | EmailAddressAlreadyRegisteredException ex) {
+                       // Throw again
+                       throw new FaceletException(ex);
+               }
+       }
+
        @Override
        public List<User> allUsers () {
                // Return it
@@ -461,6 +603,15 @@ public class AddressbookAdminUserWebSessionBean implements AddressbookAdminUserW
                this.userList = this.userBean.allUsers();
        }
 
+       /**
+        * Checks if same password is entered and that they are not empty.
+        * <p>
+        * @return Whether the same password was entered
+        */
+       private boolean isSamePasswordEntered () {
+               return ((!this.getUserPassword().isEmpty()) && (Objects.equals(this.getUserPassword(), this.getUserPasswordRepeat())));
+       }
+
        @Override
        public User lookupUserById (final Long userId) throws UserNotFoundException {
                // Init variable
index 26b2fcc209085e955762a81554807aa55e52fa0c..22c5fdbe6adde795e710a3b82cb1ffba3e7e62b8 100644 (file)
@@ -59,6 +59,13 @@ public interface AddressbookAdminUserWebSessionController extends Serializable {
         */
        boolean hasUsers ();
 
+       /**
+        * Adds user instance to database by preparing a complete user instance and
+        * sending it to the EJB. The data set in the controller is being verified,
+        * e.g. if the user name or email address is not used yet.
+        */
+       void addUser ();
+
        /**
         * Getter for birth day
         * <p>
index e6806af6ac109e2ad55a339b7606dd5b3488e28c..684658338b0cbe40262785c5214358b262059c89 100644 (file)
@@ -19,7 +19,6 @@ package org.mxchange.addressbook.beans.user;
 import java.text.MessageFormat;
 import java.util.Collections;
 import java.util.Date;
-import java.util.GregorianCalendar;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Objects;
@@ -344,12 +343,11 @@ public class AddressbookUserWebSessionBean implements AddressbookUserWebSessionC
                User user = new LoginUser();
                user.setUserName(this.getUserName());
                user.setUserProfileMode(this.getUserProfileMode());
-               user.setUserCreated(new GregorianCalendar());
 
                // Generate phone number
-               DialableLandLineNumber phone = new LandLineNumber(this.getPhoneCountry(), this.getPhoneAreaCode(), this.getPhoneNumber(), new GregorianCalendar());
-               DialableCellphoneNumber cellphone = new CellphoneNumber(this.getCellphoneCarrier(), this.getCellphoneNumber(), new GregorianCalendar());
-               DialableFaxNumber fax = new FaxNumber(this.getFaxCountry(), this.getFaxAreaCode(), this.getFaxNumber(), new GregorianCalendar());
+               DialableLandLineNumber phone = new LandLineNumber(this.getPhoneCountry(), this.getPhoneAreaCode(), this.getPhoneNumber());
+               DialableCellphoneNumber cellphone = new CellphoneNumber(this.getCellphoneCarrier(), this.getCellphoneNumber());
+               DialableFaxNumber fax = new FaxNumber(this.getFaxCountry(), this.getFaxAreaCode(), this.getFaxNumber());
 
                // Create new contact
                Contact contact = new UserContact(this.getGender(), this.getFirstName(), this.getFamilyName());
@@ -421,7 +419,6 @@ public class AddressbookUserWebSessionBean implements AddressbookUserWebSessionC
                contact.setContactComment(this.getComment());
 
                // Created timestamp and ownContact
-               contact.setContactCreated(new GregorianCalendar());
                contact.setContactOwnContact(Boolean.TRUE);
 
                // Set contact in user
@@ -429,6 +426,7 @@ public class AddressbookUserWebSessionBean implements AddressbookUserWebSessionC
 
                // Trace message
                //this.getLogger().logTrace(MessageFormat.format("createUserInstance: user={0} - EXIT!", user));
+
                // Return it
                return user;
        }
@@ -730,32 +728,32 @@ public class AddressbookUserWebSessionBean implements AddressbookUserWebSessionC
        }
 
        @Override
-       public boolean isRequiredPersonalDataSet () {
-               return ((this.getUserName() != null) &&
-                               (this.getUserProfileMode() != null) &&
+       public boolean isRequiredChangePersonalDataSet () {
+               return ((this.getUserProfileMode() != null) &&
                                (this.getGender() != null) &&
                                (this.getFirstName() != null) &&
                                (this.getFamilyName() != null) &&
                                (this.getStreet() != null) &&
                                (this.getHouseNumber() != null) &&
                                (this.getZipCode() != null) &&
-                               (this.getCity() != null) &&
-                               (this.getEmailAddress() != null) &&
-                               (this.getEmailAddressRepeat() != null) &&
-                               (this.getUserPassword() != null) &&
-                               (this.getUserPasswordRepeat() != null));
+                               (this.getCity() != null));
        }
 
        @Override
-       public boolean isRequiredChangePersonalDataSet () {
-               return ((this.getUserProfileMode() != null) &&
+       public boolean isRequiredPersonalDataSet () {
+               return ((this.getUserName() != null) &&
+                               (this.getUserProfileMode() != null) &&
                                (this.getGender() != null) &&
                                (this.getFirstName() != null) &&
                                (this.getFamilyName() != null) &&
                                (this.getStreet() != null) &&
                                (this.getHouseNumber() != null) &&
                                (this.getZipCode() != null) &&
-                               (this.getCity() != null));
+                               (this.getCity() != null) &&
+                               (this.getEmailAddress() != null) &&
+                               (this.getEmailAddressRepeat() != null) &&
+                               (this.getUserPassword() != null) &&
+                               (this.getUserPasswordRepeat() != null));
        }
 
        @Override
@@ -765,7 +763,7 @@ public class AddressbookUserWebSessionBean implements AddressbookUserWebSessionC
 
        @Override
        public boolean isSamePasswordEntered () {
-               return (Objects.equals(this.getUserPassword(), this.getUserPasswordRepeat()));
+               return ((!this.getUserPassword().isEmpty()) && (Objects.equals(this.getUserPassword(), this.getUserPasswordRepeat())));
        }
 
        @Override
index 10e49ec0c522c28da2d1a8d2c09e8cbdef73b721..ce542ad16ec0c3818689e6b3bcda044a38bb4a54 100644 (file)
@@ -35,6 +35,11 @@ import org.mxchange.jusercore.model.user.profilemodes.ProfileMode;
  */
 public interface AddressbookUserWebSessionController extends Serializable {
 
+       /**
+        * Minimum password length
+        */
+       public static final Integer MINIMUM_PASSWORD_LENGTH = 5;
+
        /**
         * Tries to lookup user by given id number. If the user is not found or the
         * account status is not CONFIRMED proper exceptions are thrown.
index 4fbd366aa600dd7561238ebe422e90f2e491b6f1..6e49447c7ade844c3820d5ab289a094a434b3e70 100644 (file)
@@ -136,4 +136,5 @@ public class AddressbookCountryConverter implements Converter {
                // Return category id
                return String.valueOf(((Country) value).getCountryId());
        }
+
 }
index 5e557208c043f82c70ce963e32f2b1d7053fcd15..f827637d5d488e0afcac22c0814664e8608398d9 100644 (file)
@@ -136,4 +136,5 @@ public class AddressbookSmsProviderConverter implements Converter {
                // Return category id
                return String.valueOf(((SmsProvider) value).getProviderId());
        }
+
 }
index d6344a02be4bc557160165c5a6395736ddbd160d..1e118a9a31e5a5a5347c9796934238347640fdcd 100644 (file)
@@ -96,8 +96,8 @@
                        <to-view-id>/basket.xhtml</to-view-id>
                </navigation-case>
                <navigation-case>
-                       <from-outcome>item_not_changed</from-outcome>
-                       <to-view-id>/errorHandler.xhtml</to-view-id>
+                       <from-outcome>exception</from-outcome>
+                       <to-view-id>/exception.xhtml</to-view-id>
                </navigation-case>
                <navigation-case>
                        <from-outcome>admin_delete_user</from-outcome>
                        <to-view-id>/admin/admin_country_edit.xhtml</to-view-id>
                </navigation-case>
        </navigation-rule>
+       <!--
+       <factory>
+               <exception-handler-factory>
+                       org.mxchange.jcoreee.exceptions.CustomExceptionHandlerFactory
+               </exception-handler-factory>
+       </factory>
+       //-->
 </faces-config>
diff --git a/web/exception.xhtml b/web/exception.xhtml
new file mode 100644 (file)
index 0000000..cbb6ce5
--- /dev/null
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+         xmlns:ui="http://java.sun.com/jsf/facelets"
+         xmlns:h="http://xmlns.jcp.org/jsf/html"
+         xmlns:f="http://xmlns.jcp.org/jsf/core"
+         >
+
+       <ui:composition template="/WEB-INF/templates/guest/guest_base.tpl">
+               <ui:define name="guest_title">#{msg.PAGE_TITLE_EXCEPTION_THROWN}</ui:define>
+
+               <ui:define name="content_header">
+                       #{msg.CONTENT_TITLE_EXCEPTION_THROWN}
+               </ui:define>
+
+               <ui:define name="content">
+                       Unfortunately an unexpected error has occurred.
+               </ui:define>
+       </ui:composition>
+</html>