]> git.mxchange.org Git - pizzaservice-ejb.git/commitdiff
Opps, 'abstract' went in by using "move-up" from NetBeans IDE ... Well, at the
authorRoland Häder <roland@mxchange.org>
Sat, 12 Aug 2017 14:18:57 +0000 (16:18 +0200)
committerRoland Häder <roland@mxchange.org>
Sat, 12 Aug 2017 14:18:57 +0000 (16:18 +0200)
end, NB is no aritificial intelligence that 100% understood your code, right?

Also fixed naming-convention, project's short name must be prefixed on all classes

Signed-off-by: Roland Häder <roland@mxchange.org>
12 files changed:
src/java/org/mxchange/jusercore/model/user/activity/PizzaUserActivitySessionBean.java
src/java/org/mxchange/pizzaapplication/model/category/AdminCategorySessionBean.java [deleted file]
src/java/org/mxchange/pizzaapplication/model/category/CategorySessionBean.java [deleted file]
src/java/org/mxchange/pizzaapplication/model/category/PizzaAdminCategorySessionBean.java [new file with mode: 0644]
src/java/org/mxchange/pizzaapplication/model/category/PizzaCategorySessionBean.java [new file with mode: 0644]
src/java/org/mxchange/pizzaapplication/model/checkout/CheckoutMessageBean.java [deleted file]
src/java/org/mxchange/pizzaapplication/model/checkout/PizzaCheckoutMessageBean.java [new file with mode: 0644]
src/java/org/mxchange/pizzaapplication/model/customer/ShopCustomerSessionBean.java [deleted file]
src/java/org/mxchange/pizzaapplication/model/product/AdminProductSessionBean.java [deleted file]
src/java/org/mxchange/pizzaapplication/model/product/PizzaAdminProductSessionBean.java [new file with mode: 0644]
src/java/org/mxchange/pizzaapplication/model/product/PizzaProductSessionBean.java [new file with mode: 0644]
src/java/org/mxchange/pizzaapplication/model/product/ProductSessionBean.java [deleted file]

index 3f4aa6c69d4f2eb78194a00c9c71217a1cdbf83c..f802f91df4b899917e176831b95ea16646c3aa2f 100644 (file)
@@ -19,13 +19,8 @@ package org.mxchange.jusercore.model.user.activity;
 import java.text.MessageFormat;
 import java.util.Arrays;
 import java.util.List;
-import java.util.Locale;
-import java.util.MissingResourceException;
-import java.util.ResourceBundle;
 import javax.ejb.EJBException;
 import javax.ejb.Stateless;
-import javax.faces.application.FacesMessage;
-import javax.faces.context.FacesContext;
 import javax.jms.JMSException;
 import javax.jms.ObjectMessage;
 import javax.persistence.Query;
@@ -40,7 +35,7 @@ import org.mxchange.jusercore.model.user.User;
  * @author Roland Häder<roland@mxchange.org>
  */
 @Stateless (name = "userActivity", description = "A bean handling the user data")
-public abstract class PizzaUserActivitySessionBean extends BaseDatabaseBean implements UserActivityLogSessionBeanRemote {
+public class PizzaUserActivitySessionBean extends BaseDatabaseBean implements UserActivityLogSessionBeanRemote {
 
        /**
         * Serial number
@@ -232,131 +227,4 @@ public abstract class PizzaUserActivitySessionBean extends BaseDatabaseBean impl
                return list;
        }
 
-       /**
-        * Returns given property key or throws an exception if not found.
-        * <p>
-        * @param parameterKey Property key
-        * <p>
-        * @return Property value
-        * <p>
-        * @throws NullPointerException If given key is not found
-        * @throws NumberFormatException If no number is given in context parameter
-        */
-       protected int getIntegerContextParameter (final String parameterKey) throws NullPointerException, NumberFormatException {
-               // Get context parameter
-               Integer contextValue = Integer.parseInt(this.getStringContextParameter(parameterKey));
-               // Return it
-               return contextValue;
-       }
-
-       /**
-        * Returns given property key or throws an exception if not found.
-        * <p>
-        * @param parameterKey Property key
-        * <p>
-        * @return Property value
-        * <p>
-        * @throws NullPointerException If given key is not found
-        */
-       protected String getStringContextParameter (final String parameterKey) throws NullPointerException {
-               // Get context parameter
-               String contextValue = FacesContext.getCurrentInstance().getExternalContext().getInitParameter(parameterKey);
-               // Is it null?
-               if (null == contextValue) {
-                       // Throw NPE
-                       throw new NullPointerException(MessageFormat.format("parameterKey={0} is not set.", parameterKey)); //NOI18N
-               }
-               // Return it
-               return contextValue;
-       }
-
-       /**
-        * Checks whether debug mode is enabled for given controller
-        * <p>
-        * @param controllerName Name of controller
-        * <p>
-        * @return Whether debug mode is enabled
-        */
-       protected boolean isDebugModeEnabled (final String controllerName) {
-               // Parameters should be valid
-               if (null == controllerName) {
-                       // Throw NPE
-                       throw new NullPointerException("controllerName is null"); //NOI18N
-               } else if (controllerName.isEmpty()) {
-                       // Is empty
-                       throw new IllegalArgumentException("controllerName is empty"); //NOI18N
-               }
-               // Try to get context parameter
-               String contextParameter = this.getStringContextParameter(String.format("is_debug_%s_enabled", controllerName)); //NOI18N
-               // Is it set and true?
-               boolean isEnabled = Boolean.parseBoolean(contextParameter) == Boolean.TRUE;
-               // Return it
-               return isEnabled;
-       }
-
-       /**
-        * Loads resource bundle for given locale. This must be implemented per
-        * project so all projects can still customize their methods. Calling
-        * ResourceBundleloadBundle() in this class means that also the bundle files
-        * must be present here.
-        * <p>
-        * @param locale Locale from e.g. FacesContext
-        * <p>
-        * @return Initialized and loaded resource bundle
-        */
-       protected abstract ResourceBundle loadResourceBundle (final Locale locale);
-
-       /**
-        * Shows a faces message for given causing exception. The message from the
-        * exception is being inserted into the message.
-        * <p>
-        * @param clientId Client id to send message to
-        * @param cause    Causing exception
-        */
-       protected void showFacesMessage (final String clientId, final Throwable cause) {
-               // Get context and add message
-               this.showFacesMessage(clientId, cause.getMessage());
-       }
-
-       /**
-        * Shows a faces message with given message (i18n) key.
-        * <p>
-        * @param clientId Client id to send message to
-        * @param i18nKey  Message key
-        * <p>
-        * @throws NullPointerException If clientId or i18nKey is null
-        * @throws IllegalArgumentException If clientId or i18nKey is empty
-        */
-       protected void showFacesMessage (final String clientId, final String i18nKey) throws NullPointerException, IllegalArgumentException {
-               // Both parameter must be valid
-               if (null == clientId) {
-                       // Throw NPE
-                       throw new NullPointerException("clientId is null"); //NOI18N
-               } else if (clientId.isEmpty()) {
-                       // Is empty
-                       throw new IllegalArgumentException("clientId is null"); //NOI18N
-               } else if (null == i18nKey) {
-                       // Throw NPE
-                       throw new NullPointerException("i18nKey is null"); //NOI18N
-               } else if (i18nKey.isEmpty()) {
-                       // Is empty
-                       throw new IllegalArgumentException("i18nKey is null"); //NOI18N
-               }
-               // Get current locale
-               Locale locale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
-               // Get bundle bundle
-               ResourceBundle bundle = this.loadResourceBundle(locale);
-               // Default is i18nKey
-               String message = MessageFormat.format("!{0}!", i18nKey); //NOI18N
-               // Try it
-               try {
-                       // Get message
-                       message = bundle.getString(i18nKey);
-               } catch (final MissingResourceException ex) {
-                       // Did not find it, ignored
-               }
-               // Get context and add message
-               FacesContext.getCurrentInstance().addMessage(clientId, new FacesMessage(message));
-       }
-
 }
diff --git a/src/java/org/mxchange/pizzaapplication/model/category/AdminCategorySessionBean.java b/src/java/org/mxchange/pizzaapplication/model/category/AdminCategorySessionBean.java
deleted file mode 100644 (file)
index 9e68174..0000000
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright (C) 2016, 2017 Roland Häder
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-package org.mxchange.pizzaapplication.model.category;
-
-import java.text.MessageFormat;
-import java.util.Locale;
-import java.util.MissingResourceException;
-import java.util.ResourceBundle;
-import javax.ejb.Stateless;
-import javax.faces.application.FacesMessage;
-import javax.faces.context.FacesContext;
-import javax.persistence.EntityNotFoundException;
-import javax.persistence.NoResultException;
-import javax.persistence.Query;
-import org.mxchange.jcoreee.database.BaseDatabaseBean;
-import org.mxchange.jproduct.exceptions.CannotAddCategoryException;
-import org.mxchange.jproduct.exceptions.CategoryTitleAlreadyUsedException;
-import org.mxchange.jproduct.model.category.Category;
-import org.mxchange.jproduct.model.category.ProductCategory;
-import org.mxchange.jshopcore.model.category.AdminCategorySessionBeanRemote;
-
-/**
- * An EJB for administrative access on categories
- * <p>
- * @author Roland Häder<roland@mxchange.org>
- */
-@Stateless (name = "admin_category", description = "An administrative bean handling product categories")
-public abstract class AdminCategorySessionBean extends BaseDatabaseBean implements AdminCategorySessionBeanRemote {
-
-       /**
-        * Serial number
-        */
-       private static final long serialVersionUID = 26_143_895_789_581L;
-
-       /**
-        * Default constructor
-        */
-       public AdminCategorySessionBean () {
-               // Call super constructor
-               super();
-       }
-
-       @Override
-       public Category doAdminAddCategory (final Category category) throws CategoryTitleAlreadyUsedException, CannotAddCategoryException {
-               // Trace message
-               this.getLoggerBeanLocal().logTrace(MessageFormat.format("doAdminAddCategory: category={0} - CALLED!", category)); //NOI18N
-
-               if (null == category) {
-                       // category is null
-                       throw new NullPointerException("category is null"); //NOI18N
-               } else if (this.getEntityManager() == null) {
-                       // Connection is not there
-                       throw new NullPointerException("connection is null"); //NOI18N
-               }
-
-               // The connection must be there
-               if (this.isCategoryTitleUsed(category)) {
-                       // Then abort here
-                       throw new CategoryTitleAlreadyUsedException(category);
-               }
-
-               // Perist the category
-               this.getEntityManager().persist(category);
-
-               // Flush it
-               this.getEntityManager().flush();
-
-               // Trace message
-               this.getLoggerBeanLocal().logTrace(MessageFormat.format("doAdminAddCategory: category={0} - EXIT!", category)); //NOI18N
-
-               // Return it
-               return category;
-       }
-
-       /**
-        * Checks if the category's title has already been used as they need to be
-        * unique. This method works case-insensitive. Any spaces, new-line,
-        * carriage-return or tabulator characters are trimmed away. If the title
-        * has been used already, for performance reasons, the id and parent id are
-        * set in the category object.
-        * <p>
-        * @param category Category instance
-        * <p>
-        * @return Whether the category's title has been used
-        */
-       private boolean isCategoryTitleUsed (final Category category) {
-               // Trace message
-               this.getLoggerBeanLocal().logTrace(MessageFormat.format("isCategoryTitleUsed: category={0} - CALLED!", category)); //NOI18N
-
-               // The connection must be there
-               if (null == category) {
-                       // category is null
-                       throw new NullPointerException("category is null"); //NOI18N
-               } else if (this.getEntityManager() == null) {
-                       // Connection is not there
-                       throw new NullPointerException("connection is null"); //NOI18N
-               }
-
-               // Default is not found
-               boolean isUsed = false;
-
-               // Debug message
-               this.getLoggerBeanLocal().logDebug(MessageFormat.format("isCategoryTitleUsed: category.id={0},category.title={1},category.parentId={2}", category.getCategoryId(), category.getCategoryTitle(), category.getParentCategory())); //NOI18N
-
-               // Try to locate it
-               try {
-                       // Get query instance
-                       Query query = this.getEntityManager().createQuery("SELECT c FROM category AS c WHERE LOWER(c.categoryTitle) = LOWER(:param)", ProductCategory.class); //NOI18N
-                       query.setParameter("param", category.getCategoryTitle()); //NOI18N
-                       Category cat = (Category) query.getSingleResult();
-
-                       // Is found, so copy the object
-                       category.copyAll(cat);
-
-                       // Mark as found
-                       isUsed = true;
-               } catch (final EntityNotFoundException | NoResultException e) {
-                       // Not found
-                       this.getLoggerBeanLocal().logWarning(e.getMessage());
-               }
-
-               // Trace message
-               this.getLoggerBeanLocal().logTrace(MessageFormat.format("isCategoryTitleUsed: isUsed={0} - EXIT!", isUsed)); //NOI18N
-
-               // Return it
-               return isUsed;
-       }
-
-       /**
-        * Returns given property key or throws an exception if not found.
-        * <p>
-        * @param parameterKey Property key
-        * <p>
-        * @return Property value
-        * <p>
-        * @throws NullPointerException If given key is not found
-        * @throws NumberFormatException If no number is given in context parameter
-        */
-       protected int getIntegerContextParameter (final String parameterKey) throws NullPointerException, NumberFormatException {
-               // Get context parameter
-               Integer contextValue = Integer.parseInt(this.getStringContextParameter(parameterKey));
-               // Return it
-               return contextValue;
-       }
-
-       /**
-        * Returns given property key or throws an exception if not found.
-        * <p>
-        * @param parameterKey Property key
-        * <p>
-        * @return Property value
-        * <p>
-        * @throws NullPointerException If given key is not found
-        */
-       protected String getStringContextParameter (final String parameterKey) throws NullPointerException {
-               // Get context parameter
-               String contextValue = FacesContext.getCurrentInstance().getExternalContext().getInitParameter(parameterKey);
-               // Is it null?
-               if (null == contextValue) {
-                       // Throw NPE
-                       throw new NullPointerException(MessageFormat.format("parameterKey={0} is not set.", parameterKey)); //NOI18N
-               }
-               // Return it
-               return contextValue;
-       }
-
-       /**
-        * Checks whether debug mode is enabled for given controller
-        * <p>
-        * @param controllerName Name of controller
-        * <p>
-        * @return Whether debug mode is enabled
-        */
-       protected boolean isDebugModeEnabled (final String controllerName) {
-               // Parameters should be valid
-               if (null == controllerName) {
-                       // Throw NPE
-                       throw new NullPointerException("controllerName is null"); //NOI18N
-               } else if (controllerName.isEmpty()) {
-                       // Is empty
-                       throw new IllegalArgumentException("controllerName is empty"); //NOI18N
-               }
-               // Try to get context parameter
-               String contextParameter = this.getStringContextParameter(String.format("is_debug_%s_enabled", controllerName)); //NOI18N
-               // Is it set and true?
-               boolean isEnabled = Boolean.parseBoolean(contextParameter) == Boolean.TRUE;
-               // Return it
-               return isEnabled;
-       }
-
-       /**
-        * Loads resource bundle for given locale. This must be implemented per
-        * project so all projects can still customize their methods. Calling
-        * ResourceBundleloadBundle() in this class means that also the bundle files
-        * must be present here.
-        * <p>
-        * @param locale Locale from e.g. FacesContext
-        * <p>
-        * @return Initialized and loaded resource bundle
-        */
-       protected abstract ResourceBundle loadResourceBundle (final Locale locale);
-
-       /**
-        * Shows a faces message for given causing exception. The message from the
-        * exception is being inserted into the message.
-        * <p>
-        * @param clientId Client id to send message to
-        * @param cause    Causing exception
-        */
-       protected void showFacesMessage (final String clientId, final Throwable cause) {
-               // Get context and add message
-               this.showFacesMessage(clientId, cause.getMessage());
-       }
-
-       /**
-        * Shows a faces message with given message (i18n) key.
-        * <p>
-        * @param clientId Client id to send message to
-        * @param i18nKey  Message key
-        * <p>
-        * @throws NullPointerException If clientId or i18nKey is null
-        * @throws IllegalArgumentException If clientId or i18nKey is empty
-        */
-       protected void showFacesMessage (final String clientId, final String i18nKey) throws NullPointerException, IllegalArgumentException {
-               // Both parameter must be valid
-               if (null == clientId) {
-                       // Throw NPE
-                       throw new NullPointerException("clientId is null"); //NOI18N
-               } else if (clientId.isEmpty()) {
-                       // Is empty
-                       throw new IllegalArgumentException("clientId is null"); //NOI18N
-               } else if (null == i18nKey) {
-                       // Throw NPE
-                       throw new NullPointerException("i18nKey is null"); //NOI18N
-               } else if (i18nKey.isEmpty()) {
-                       // Is empty
-                       throw new IllegalArgumentException("i18nKey is null"); //NOI18N
-               }
-               // Get current locale
-               Locale locale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
-               // Get bundle bundle
-               ResourceBundle bundle = this.loadResourceBundle(locale);
-               // Default is i18nKey
-               String message = MessageFormat.format("!{0}!", i18nKey); //NOI18N
-               // Try it
-               try {
-                       // Get message
-                       message = bundle.getString(i18nKey);
-               } catch (final MissingResourceException ex) {
-                       // Did not find it, ignored
-               }
-               // Get context and add message
-               FacesContext.getCurrentInstance().addMessage(clientId, new FacesMessage(message));
-       }
-
-}
diff --git a/src/java/org/mxchange/pizzaapplication/model/category/CategorySessionBean.java b/src/java/org/mxchange/pizzaapplication/model/category/CategorySessionBean.java
deleted file mode 100644 (file)
index 683246f..0000000
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright (C) 2016, 2017 Roland Häder
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-package org.mxchange.pizzaapplication.model.category;
-
-import java.text.MessageFormat;
-import java.util.List;
-import java.util.Locale;
-import java.util.MissingResourceException;
-import java.util.ResourceBundle;
-import javax.ejb.Stateless;
-import javax.faces.application.FacesMessage;
-import javax.faces.context.FacesContext;
-import javax.persistence.Query;
-import org.mxchange.jcoreee.database.BaseDatabaseBean;
-import org.mxchange.jproduct.model.category.Category;
-import org.mxchange.jproduct.model.category.ProductCategory;
-import org.mxchange.jshopcore.model.category.CategorySessionBeanRemote;
-
-/**
- * Main shop class
- * <p>
- * @author Roland Häder<roland@mxchange.org>
- */
-@Stateless (name = "category", description = "A bean handling categories for all others (non-admin)")
-public abstract class CategorySessionBean extends BaseDatabaseBean implements CategorySessionBeanRemote {
-
-       /**
-        * Serial number
-        */
-       private static final long serialVersionUID = 58_137_539_530_279L;
-
-       /**
-        * Default constructor
-        */
-       public CategorySessionBean () {
-               // Call super constructor
-               super();
-       }
-
-       @Override
-       @SuppressWarnings ("unchecked")
-       public List<Category> getAllCategories () {
-               // Trace message
-               this.getLoggerBeanLocal().logTrace("getAllCategories: CALLED!"); //NOI18N
-
-               // The connection must be there
-               if (this.getEntityManager() == null) {
-                       // Connection is not there
-                       throw new NullPointerException("connection is null"); //NOI18N
-               }
-
-               // Create statement
-               Query query = this.getEntityManager().createQuery("SELECT c FROM category AS c ORDER BY c.categoryId ASC", ProductCategory.class);
-
-               // Get result
-               List<Category> list = query.getResultList();
-
-               // Trace message
-               this.getLoggerBeanLocal().logTrace(MessageFormat.format("getAllCategories: list({0})={1} - EXIT!", list.size(), list)); //NOI18N
-
-               // Return it
-               return list;
-       }
-
-       /**
-        * Returns given property key or throws an exception if not found.
-        * <p>
-        * @param parameterKey Property key
-        * <p>
-        * @return Property value
-        * <p>
-        * @throws NullPointerException If given key is not found
-        * @throws NumberFormatException If no number is given in context parameter
-        */
-       protected int getIntegerContextParameter (final String parameterKey) throws NullPointerException, NumberFormatException {
-               // Get context parameter
-               Integer contextValue = Integer.parseInt(this.getStringContextParameter(parameterKey));
-               // Return it
-               return contextValue;
-       }
-
-       /**
-        * Returns given property key or throws an exception if not found.
-        * <p>
-        * @param parameterKey Property key
-        * <p>
-        * @return Property value
-        * <p>
-        * @throws NullPointerException If given key is not found
-        */
-       protected String getStringContextParameter (final String parameterKey) throws NullPointerException {
-               // Get context parameter
-               String contextValue = FacesContext.getCurrentInstance().getExternalContext().getInitParameter(parameterKey);
-               // Is it null?
-               if (null == contextValue) {
-                       // Throw NPE
-                       throw new NullPointerException(MessageFormat.format("parameterKey={0} is not set.", parameterKey)); //NOI18N
-               }
-               // Return it
-               return contextValue;
-       }
-
-       /**
-        * Checks whether debug mode is enabled for given controller
-        * <p>
-        * @param controllerName Name of controller
-        * <p>
-        * @return Whether debug mode is enabled
-        */
-       protected boolean isDebugModeEnabled (final String controllerName) {
-               // Parameters should be valid
-               if (null == controllerName) {
-                       // Throw NPE
-                       throw new NullPointerException("controllerName is null"); //NOI18N
-               } else if (controllerName.isEmpty()) {
-                       // Is empty
-                       throw new IllegalArgumentException("controllerName is empty"); //NOI18N
-               }
-               // Try to get context parameter
-               String contextParameter = this.getStringContextParameter(String.format("is_debug_%s_enabled", controllerName)); //NOI18N
-               // Is it set and true?
-               boolean isEnabled = Boolean.parseBoolean(contextParameter) == Boolean.TRUE;
-               // Return it
-               return isEnabled;
-       }
-
-       /**
-        * Loads resource bundle for given locale. This must be implemented per
-        * project so all projects can still customize their methods. Calling
-        * ResourceBundleloadBundle() in this class means that also the bundle files
-        * must be present here.
-        * <p>
-        * @param locale Locale from e.g. FacesContext
-        * <p>
-        * @return Initialized and loaded resource bundle
-        */
-       protected abstract ResourceBundle loadResourceBundle (final Locale locale);
-
-       /**
-        * Shows a faces message for given causing exception. The message from the
-        * exception is being inserted into the message.
-        * <p>
-        * @param clientId Client id to send message to
-        * @param cause    Causing exception
-        */
-       protected void showFacesMessage (final String clientId, final Throwable cause) {
-               // Get context and add message
-               this.showFacesMessage(clientId, cause.getMessage());
-       }
-
-       /**
-        * Shows a faces message with given message (i18n) key.
-        * <p>
-        * @param clientId Client id to send message to
-        * @param i18nKey  Message key
-        * <p>
-        * @throws NullPointerException If clientId or i18nKey is null
-        * @throws IllegalArgumentException If clientId or i18nKey is empty
-        */
-       protected void showFacesMessage (final String clientId, final String i18nKey) throws NullPointerException, IllegalArgumentException {
-               // Both parameter must be valid
-               if (null == clientId) {
-                       // Throw NPE
-                       throw new NullPointerException("clientId is null"); //NOI18N
-               } else if (clientId.isEmpty()) {
-                       // Is empty
-                       throw new IllegalArgumentException("clientId is null"); //NOI18N
-               } else if (null == i18nKey) {
-                       // Throw NPE
-                       throw new NullPointerException("i18nKey is null"); //NOI18N
-               } else if (i18nKey.isEmpty()) {
-                       // Is empty
-                       throw new IllegalArgumentException("i18nKey is null"); //NOI18N
-               }
-               // Get current locale
-               Locale locale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
-               // Get bundle bundle
-               ResourceBundle bundle = this.loadResourceBundle(locale);
-               // Default is i18nKey
-               String message = MessageFormat.format("!{0}!", i18nKey); //NOI18N
-               // Try it
-               try {
-                       // Get message
-                       message = bundle.getString(i18nKey);
-               } catch (final MissingResourceException ex) {
-                       // Did not find it, ignored
-               }
-               // Get context and add message
-               FacesContext.getCurrentInstance().addMessage(clientId, new FacesMessage(message));
-       }
-
-}
diff --git a/src/java/org/mxchange/pizzaapplication/model/category/PizzaAdminCategorySessionBean.java b/src/java/org/mxchange/pizzaapplication/model/category/PizzaAdminCategorySessionBean.java
new file mode 100644 (file)
index 0000000..e2a7ca5
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2016, 2017 Roland Häder
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.mxchange.pizzaapplication.model.category;
+
+import java.text.MessageFormat;
+import javax.ejb.Stateless;
+import javax.persistence.EntityNotFoundException;
+import javax.persistence.NoResultException;
+import javax.persistence.Query;
+import org.mxchange.jcoreee.database.BaseDatabaseBean;
+import org.mxchange.jproduct.exceptions.CannotAddCategoryException;
+import org.mxchange.jproduct.exceptions.CategoryTitleAlreadyUsedException;
+import org.mxchange.jproduct.model.category.Category;
+import org.mxchange.jproduct.model.category.ProductCategory;
+import org.mxchange.jshopcore.model.category.AdminCategorySessionBeanRemote;
+
+/**
+ * An EJB for administrative access on categories
+ * <p>
+ * @author Roland Häder<roland@mxchange.org>
+ */
+@Stateless (name = "admin_category", description = "An administrative bean handling product categories")
+public class PizzaAdminCategorySessionBean extends BaseDatabaseBean implements AdminCategorySessionBeanRemote {
+
+       /**
+        * Serial number
+        */
+       private static final long serialVersionUID = 26_143_895_789_581L;
+
+       /**
+        * Default constructor
+        */
+       public PizzaAdminCategorySessionBean () {
+               // Call super constructor
+               super();
+       }
+
+       @Override
+       public Category doAdminAddCategory (final Category category) throws CategoryTitleAlreadyUsedException, CannotAddCategoryException {
+               // Trace message
+               this.getLoggerBeanLocal().logTrace(MessageFormat.format("doAdminAddCategory: category={0} - CALLED!", category)); //NOI18N
+
+               if (null == category) {
+                       // category is null
+                       throw new NullPointerException("category is null"); //NOI18N
+               } else if (this.getEntityManager() == null) {
+                       // Connection is not there
+                       throw new NullPointerException("connection is null"); //NOI18N
+               }
+
+               // The connection must be there
+               if (this.isCategoryTitleUsed(category)) {
+                       // Then abort here
+                       throw new CategoryTitleAlreadyUsedException(category);
+               }
+
+               // Perist the category
+               this.getEntityManager().persist(category);
+
+               // Flush it
+               this.getEntityManager().flush();
+
+               // Trace message
+               this.getLoggerBeanLocal().logTrace(MessageFormat.format("doAdminAddCategory: category={0} - EXIT!", category)); //NOI18N
+
+               // Return it
+               return category;
+       }
+
+       /**
+        * Checks if the category's title has already been used as they need to be
+        * unique. This method works case-insensitive. Any spaces, new-line,
+        * carriage-return or tabulator characters are trimmed away. If the title
+        * has been used already, for performance reasons, the id and parent id are
+        * set in the category object.
+        * <p>
+        * @param category Category instance
+        * <p>
+        * @return Whether the category's title has been used
+        */
+       private boolean isCategoryTitleUsed (final Category category) {
+               // Trace message
+               this.getLoggerBeanLocal().logTrace(MessageFormat.format("isCategoryTitleUsed: category={0} - CALLED!", category)); //NOI18N
+
+               // The connection must be there
+               if (null == category) {
+                       // category is null
+                       throw new NullPointerException("category is null"); //NOI18N
+               } else if (this.getEntityManager() == null) {
+                       // Connection is not there
+                       throw new NullPointerException("connection is null"); //NOI18N
+               }
+
+               // Default is not found
+               boolean isUsed = false;
+
+               // Debug message
+               this.getLoggerBeanLocal().logDebug(MessageFormat.format("isCategoryTitleUsed: category.id={0},category.title={1},category.parentId={2}", category.getCategoryId(), category.getCategoryTitle(), category.getParentCategory())); //NOI18N
+
+               // Try to locate it
+               try {
+                       // Get query instance
+                       Query query = this.getEntityManager().createQuery("SELECT c FROM category AS c WHERE LOWER(c.categoryTitle) = LOWER(:param)", ProductCategory.class); //NOI18N
+                       query.setParameter("param", category.getCategoryTitle()); //NOI18N
+                       Category cat = (Category) query.getSingleResult();
+
+                       // Is found, so copy the object
+                       category.copyAll(cat);
+
+                       // Mark as found
+                       isUsed = true;
+               } catch (final EntityNotFoundException | NoResultException e) {
+                       // Not found
+                       this.getLoggerBeanLocal().logWarning(e.getMessage());
+               }
+
+               // Trace message
+               this.getLoggerBeanLocal().logTrace(MessageFormat.format("isCategoryTitleUsed: isUsed={0} - EXIT!", isUsed)); //NOI18N
+
+               // Return it
+               return isUsed;
+       }
+
+}
diff --git a/src/java/org/mxchange/pizzaapplication/model/category/PizzaCategorySessionBean.java b/src/java/org/mxchange/pizzaapplication/model/category/PizzaCategorySessionBean.java
new file mode 100644 (file)
index 0000000..dddbc24
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2016, 2017 Roland Häder
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.mxchange.pizzaapplication.model.category;
+
+import java.text.MessageFormat;
+import java.util.List;
+import javax.ejb.Stateless;
+import javax.persistence.Query;
+import org.mxchange.jcoreee.database.BaseDatabaseBean;
+import org.mxchange.jproduct.model.category.Category;
+import org.mxchange.jproduct.model.category.ProductCategory;
+import org.mxchange.jshopcore.model.category.CategorySessionBeanRemote;
+
+/**
+ * Main shop class
+ * <p>
+ * @author Roland Häder<roland@mxchange.org>
+ */
+@Stateless (name = "category", description = "A bean handling categories for all others (non-admin)")
+public class PizzaCategorySessionBean extends BaseDatabaseBean implements CategorySessionBeanRemote {
+
+       /**
+        * Serial number
+        */
+       private static final long serialVersionUID = 58_137_539_530_279L;
+
+       /**
+        * Default constructor
+        */
+       public PizzaCategorySessionBean () {
+               // Call super constructor
+               super();
+       }
+
+       @Override
+       @SuppressWarnings ("unchecked")
+       public List<Category> getAllCategories () {
+               // Trace message
+               this.getLoggerBeanLocal().logTrace("getAllCategories: CALLED!"); //NOI18N
+
+               // The connection must be there
+               if (this.getEntityManager() == null) {
+                       // Connection is not there
+                       throw new NullPointerException("connection is null"); //NOI18N
+               }
+
+               // Create statement
+               Query query = this.getEntityManager().createQuery("SELECT c FROM category AS c ORDER BY c.categoryId ASC", ProductCategory.class);
+
+               // Get result
+               List<Category> list = query.getResultList();
+
+               // Trace message
+               this.getLoggerBeanLocal().logTrace(MessageFormat.format("getAllCategories: list({0})={1} - EXIT!", list.size(), list)); //NOI18N
+
+               // Return it
+               return list;
+       }
+
+}
diff --git a/src/java/org/mxchange/pizzaapplication/model/checkout/CheckoutMessageBean.java b/src/java/org/mxchange/pizzaapplication/model/checkout/CheckoutMessageBean.java
deleted file mode 100644 (file)
index b2bfcbb..0000000
+++ /dev/null
@@ -1,347 +0,0 @@
-/*
- * Copyright (C) 2016, 2017 Roland Häder
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-package org.mxchange.pizzaapplication.model.checkout;
-
-import java.io.Serializable;
-import java.text.MessageFormat;
-import java.util.List;
-import java.util.Locale;
-import java.util.MissingResourceException;
-import java.util.ResourceBundle;
-import javax.ejb.ActivationConfigProperty;
-import javax.ejb.EJB;
-import javax.ejb.MessageDriven;
-import javax.faces.application.FacesMessage;
-import javax.faces.context.FacesContext;
-import javax.jms.JMSException;
-import javax.jms.Message;
-import javax.jms.MessageListener;
-import javax.jms.ObjectMessage;
-import javax.naming.Context;
-import javax.naming.InitialContext;
-import javax.naming.NamingException;
-import org.mxchange.jcoreee.bean.BaseBean;
-import org.mxchange.jcoreeelogger.beans.local.logger.Log;
-import org.mxchange.jcoreeelogger.beans.local.logger.LoggerBeanLocal;
-import org.mxchange.jcustomercore.exceptions.CustomerAlreadyRegisteredException;
-import org.mxchange.jcustomercore.model.customer.Customer;
-import org.mxchange.jcustomercore.model.customer.CustomerSessionBeanRemote;
-import org.mxchange.jshopcore.model.basket.AddableBasketItem;
-import org.mxchange.jshopcore.model.basket.BasketSessionBeanRemote;
-import org.mxchange.jshopcore.model.receipt.ReceiptBeanRemote;
-import org.mxchange.jshopcore.wrapper.WrapableCheckout;
-
-/**
- * A message-driven bean for checkouts
- * <p>
- * @author Roland Häder<roland@mxchange.org>
- */
-@MessageDriven (
-               name = "checkout",
-               description = "A message bean for shop checkouts",
-               activationConfig = {
-                       @ActivationConfigProperty (propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
-                       @ActivationConfigProperty (propertyName = "destinationLookup", propertyValue = "jms/shopCheckoutQueue")
-               }
-)
-public abstract class CheckoutMessageBean extends BaseBean implements MessageListener {
-
-       /**
-        * Serial number
-        */
-       private static final long serialVersionUID = 1_869_867_265_401L;
-
-       /**
-        * Basket bean
-        */
-       @EJB
-       private BasketSessionBeanRemote basketBean;
-
-       /**
-        * Customer instance
-        */
-       @EJB
-       private CustomerSessionBeanRemote customerBean;
-
-       /**
-        * Logger bean
-        */
-       @Log
-       private LoggerBeanLocal loggerBeanLocal;
-
-       /**
-        * Receipt bean
-        */
-       @EJB
-       private ReceiptBeanRemote receiptBean;
-
-       /**
-        * Default constructor
-        */
-       public CheckoutMessageBean () {
-               // Call super constructor
-               super();
-
-               try {
-                       // Get initial context
-                       Context context = new InitialContext();
-
-                       // Lookup logger
-                       this.loggerBeanLocal = (LoggerBeanLocal) context.lookup("java:global/jcore-logger-ejb/logger!org.mxchange.jcoreeelogger.beans.local.logger.LoggerBeanLocal"); //NOI18N
-               } catch (final NamingException ex) {
-                       // Continue to throw
-                       throw new RuntimeException(MessageFormat.format("context.lookup() failed: {0}", ex.getMessage()), ex); //NOI18N
-               }
-       }
-
-       @Override
-       public void onMessage (final Message message) {
-               // Trace message
-               this.loggerBeanLocal.logTrace(MessageFormat.format("onMessage: message={0} - CALLED!", message)); //NOI18N
-
-               // Is the message castable to ObjectMessage?
-               if (null == message) {
-                       // message is null
-                       throw new NullPointerException("message is null"); //NOI18N
-               } else if (!(message instanceof ObjectMessage)) {
-                       // Not castable
-                       throw new ClassCastException(MessageFormat.format("message cannot be casted to ObjectMessage: {0}", message)); //NOI18N
-               }
-
-               // Securely cast it
-               ObjectMessage objectMessage = (ObjectMessage) message;
-
-               // Init instance
-               Serializable object;
-
-               try {
-                       // Get object from it
-                       object = objectMessage.getObject();
-               } catch (final JMSException ex) {
-                       // Log exception ...
-                       this.loggerBeanLocal.logException(ex);
-
-                       // ... and don't continue
-                       return;
-               }
-
-               // Debug message
-               this.loggerBeanLocal.logDebug(MessageFormat.format("onMessage: object={0}", object)); //NOI18N
-
-               // Does this object implement WrapableCheckout ?
-               if (null == object) {
-                       // object cannot be null
-                       throw new NullPointerException("object is null"); //NOI18N
-               } else if (!(object instanceof WrapableCheckout)) {
-                       // Not proper interface used
-                       throw new ClassCastException(MessageFormat.format("object does not implement WrapableCheckout: {0}", object)); //NOI18N
-               }
-
-               // Securely cast it
-               WrapableCheckout checkout = (WrapableCheckout) object;
-
-               // Get customer and list from it
-               Customer customer = checkout.getCustomer();
-               List<AddableBasketItem> orderedItems = checkout.getList();
-
-               // Debug message
-               this.loggerBeanLocal.logDebug(MessageFormat.format("onMessage: customerInstance={0},itemList={1}", customer, orderedItems)); //NOI18N
-
-               // Check both on null
-               if (null == customer) {
-                       // customer is null
-                       throw new NullPointerException("customer is null"); //NOI18N
-               } else if (null == orderedItems) {
-                       // list is null
-                       throw new NullPointerException("list is null"); //NOI18N
-               }
-
-               try {
-                       // Is the customer already registered?
-                       if (this.customerBean.isRegistered(customer)) {
-                               // Already registered, so get all data
-                               customer = this.customerBean.fillCustomerData(customer);
-                       } else {
-                               // Register customer first, this generates a customer number
-                               customer = this.customerBean.registerCustomer(customer);
-                       }
-               } catch (final CustomerAlreadyRegisteredException ex) {
-                       // Log exception and abort
-                       this.loggerBeanLocal.logException(ex);
-                       return;
-               }
-
-               // Is the instance set?
-               if (null == customer) {
-                       // Customer is null
-                       throw new NullPointerException("customer is null"); //NOI18N
-               }
-
-               // Make sure the number has been regenerated
-               if (customer.getCustomerNumber() == null) {
-                       // Not assigned
-                       throw new NullPointerException(MessageFormat.format("registerCustomer() did not create a custome number: customerInstance={0}", customer)); //NOI18N
-               }
-
-               // Now add the ordered item list
-               String accessKey = this.basketBean.registerItems(customer, orderedItems);
-
-               // Debug message
-               this.loggerBeanLocal.logDebug(MessageFormat.format("onMessage: accessKey={0}", accessKey)); //NOI18N
-
-               // Should not be null
-               if (null == accessKey) {
-                       // Abort here
-                       throw new NullPointerException("accessKey is null"); //NOI18N
-               }
-
-               // Set access key and customer
-               this.receiptBean.setAccessKey(accessKey);
-               this.receiptBean.setCustomer(customer);
-
-               // Trace message
-               this.loggerBeanLocal.logTrace("onMessage: EXIT!"); //NOI18N
-       }
-
-       /**
-        * Returns given property key or throws an exception if not found.
-        * <p>
-        * @param parameterKey Property key
-        * <p>
-        * @return Property value
-        * <p>
-        * @throws NullPointerException If given key is not found
-        * @throws NumberFormatException If no number is given in context parameter
-        */
-       protected int getIntegerContextParameter (final String parameterKey) throws NullPointerException, NumberFormatException {
-               // Get context parameter
-               Integer contextValue = Integer.parseInt(this.getStringContextParameter(parameterKey));
-               // Return it
-               return contextValue;
-       }
-
-       /**
-        * Returns given property key or throws an exception if not found.
-        * <p>
-        * @param parameterKey Property key
-        * <p>
-        * @return Property value
-        * <p>
-        * @throws NullPointerException If given key is not found
-        */
-       protected String getStringContextParameter (final String parameterKey) throws NullPointerException {
-               // Get context parameter
-               String contextValue = FacesContext.getCurrentInstance().getExternalContext().getInitParameter(parameterKey);
-               // Is it null?
-               if (null == contextValue) {
-                       // Throw NPE
-                       throw new NullPointerException(MessageFormat.format("parameterKey={0} is not set.", parameterKey)); //NOI18N
-               }
-               // Return it
-               return contextValue;
-       }
-
-       /**
-        * Checks whether debug mode is enabled for given controller
-        * <p>
-        * @param controllerName Name of controller
-        * <p>
-        * @return Whether debug mode is enabled
-        */
-       protected boolean isDebugModeEnabled (final String controllerName) {
-               // Parameters should be valid
-               if (null == controllerName) {
-                       // Throw NPE
-                       throw new NullPointerException("controllerName is null"); //NOI18N
-               } else if (controllerName.isEmpty()) {
-                       // Is empty
-                       throw new IllegalArgumentException("controllerName is empty"); //NOI18N
-               }
-               // Try to get context parameter
-               String contextParameter = this.getStringContextParameter(String.format("is_debug_%s_enabled", controllerName)); //NOI18N
-               // Is it set and true?
-               boolean isEnabled = Boolean.parseBoolean(contextParameter) == Boolean.TRUE;
-               // Return it
-               return isEnabled;
-       }
-
-       /**
-        * Loads resource bundle for given locale. This must be implemented per
-        * project so all projects can still customize their methods. Calling
-        * ResourceBundleloadBundle() in this class means that also the bundle files
-        * must be present here.
-        * <p>
-        * @param locale Locale from e.g. FacesContext
-        * <p>
-        * @return Initialized and loaded resource bundle
-        */
-       protected abstract ResourceBundle loadResourceBundle (final Locale locale);
-
-       /**
-        * Shows a faces message for given causing exception. The message from the
-        * exception is being inserted into the message.
-        * <p>
-        * @param clientId Client id to send message to
-        * @param cause    Causing exception
-        */
-       protected void showFacesMessage (final String clientId, final Throwable cause) {
-               // Get context and add message
-               this.showFacesMessage(clientId, cause.getMessage());
-       }
-
-       /**
-        * Shows a faces message with given message (i18n) key.
-        * <p>
-        * @param clientId Client id to send message to
-        * @param i18nKey  Message key
-        * <p>
-        * @throws NullPointerException If clientId or i18nKey is null
-        * @throws IllegalArgumentException If clientId or i18nKey is empty
-        */
-       protected void showFacesMessage (final String clientId, final String i18nKey) throws NullPointerException, IllegalArgumentException {
-               // Both parameter must be valid
-               if (null == clientId) {
-                       // Throw NPE
-                       throw new NullPointerException("clientId is null"); //NOI18N
-               } else if (clientId.isEmpty()) {
-                       // Is empty
-                       throw new IllegalArgumentException("clientId is null"); //NOI18N
-               } else if (null == i18nKey) {
-                       // Throw NPE
-                       throw new NullPointerException("i18nKey is null"); //NOI18N
-               } else if (i18nKey.isEmpty()) {
-                       // Is empty
-                       throw new IllegalArgumentException("i18nKey is null"); //NOI18N
-               }
-               // Get current locale
-               Locale locale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
-               // Get bundle bundle
-               ResourceBundle bundle = this.loadResourceBundle(locale);
-               // Default is i18nKey
-               String message = MessageFormat.format("!{0}!", i18nKey); //NOI18N
-               // Try it
-               try {
-                       // Get message
-                       message = bundle.getString(i18nKey);
-               } catch (final MissingResourceException ex) {
-                       // Did not find it, ignored
-               }
-               // Get context and add message
-               FacesContext.getCurrentInstance().addMessage(clientId, new FacesMessage(message));
-       }
-
-}
diff --git a/src/java/org/mxchange/pizzaapplication/model/checkout/PizzaCheckoutMessageBean.java b/src/java/org/mxchange/pizzaapplication/model/checkout/PizzaCheckoutMessageBean.java
new file mode 100644 (file)
index 0000000..723653d
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2016, 2017 Roland Häder
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.mxchange.pizzaapplication.model.checkout;
+
+import java.io.Serializable;
+import java.text.MessageFormat;
+import java.util.List;
+import javax.ejb.ActivationConfigProperty;
+import javax.ejb.EJB;
+import javax.ejb.MessageDriven;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageListener;
+import javax.jms.ObjectMessage;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import org.mxchange.jcoreee.bean.BaseBean;
+import org.mxchange.jcoreeelogger.beans.local.logger.Log;
+import org.mxchange.jcoreeelogger.beans.local.logger.LoggerBeanLocal;
+import org.mxchange.jcustomercore.exceptions.CustomerAlreadyRegisteredException;
+import org.mxchange.jcustomercore.model.customer.Customer;
+import org.mxchange.jcustomercore.model.customer.CustomerSessionBeanRemote;
+import org.mxchange.jshopcore.model.basket.AddableBasketItem;
+import org.mxchange.jshopcore.model.basket.BasketSessionBeanRemote;
+import org.mxchange.jshopcore.model.receipt.ReceiptBeanRemote;
+import org.mxchange.jshopcore.wrapper.WrapableCheckout;
+
+/**
+ * A message-driven bean for checkouts
+ * <p>
+ * @author Roland Häder<roland@mxchange.org>
+ */
+@MessageDriven (
+               name = "checkout",
+               description = "A message bean for shop checkouts",
+               activationConfig = {
+                       @ActivationConfigProperty (propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
+                       @ActivationConfigProperty (propertyName = "destinationLookup", propertyValue = "jms/shopCheckoutQueue")
+               }
+)
+public class PizzaCheckoutMessageBean extends BaseBean implements MessageListener {
+
+       /**
+        * Serial number
+        */
+       private static final long serialVersionUID = 1_869_867_265_401L;
+
+       /**
+        * Basket bean
+        */
+       @EJB
+       private BasketSessionBeanRemote basketBean;
+
+       /**
+        * Customer instance
+        */
+       @EJB
+       private CustomerSessionBeanRemote customerBean;
+
+       /**
+        * Logger bean
+        */
+       @Log
+       private LoggerBeanLocal loggerBeanLocal;
+
+       /**
+        * Receipt bean
+        */
+       @EJB
+       private ReceiptBeanRemote receiptBean;
+
+       /**
+        * Default constructor
+        */
+       public PizzaCheckoutMessageBean () {
+               // Call super constructor
+               super();
+
+               try {
+                       // Get initial context
+                       Context context = new InitialContext();
+
+                       // Lookup logger
+                       this.loggerBeanLocal = (LoggerBeanLocal) context.lookup("java:global/jcore-logger-ejb/logger!org.mxchange.jcoreeelogger.beans.local.logger.LoggerBeanLocal"); //NOI18N
+               } catch (final NamingException ex) {
+                       // Continue to throw
+                       throw new RuntimeException(MessageFormat.format("context.lookup() failed: {0}", ex.getMessage()), ex); //NOI18N
+               }
+       }
+
+       @Override
+       public void onMessage (final Message message) {
+               // Trace message
+               this.loggerBeanLocal.logTrace(MessageFormat.format("onMessage: message={0} - CALLED!", message)); //NOI18N
+
+               // Is the message castable to ObjectMessage?
+               if (null == message) {
+                       // message is null
+                       throw new NullPointerException("message is null"); //NOI18N
+               } else if (!(message instanceof ObjectMessage)) {
+                       // Not castable
+                       throw new ClassCastException(MessageFormat.format("message cannot be casted to ObjectMessage: {0}", message)); //NOI18N
+               }
+
+               // Securely cast it
+               ObjectMessage objectMessage = (ObjectMessage) message;
+
+               // Init instance
+               Serializable object;
+
+               try {
+                       // Get object from it
+                       object = objectMessage.getObject();
+               } catch (final JMSException ex) {
+                       // Log exception ...
+                       this.loggerBeanLocal.logException(ex);
+
+                       // ... and don't continue
+                       return;
+               }
+
+               // Debug message
+               this.loggerBeanLocal.logDebug(MessageFormat.format("onMessage: object={0}", object)); //NOI18N
+
+               // Does this object implement WrapableCheckout ?
+               if (null == object) {
+                       // object cannot be null
+                       throw new NullPointerException("object is null"); //NOI18N
+               } else if (!(object instanceof WrapableCheckout)) {
+                       // Not proper interface used
+                       throw new ClassCastException(MessageFormat.format("object does not implement WrapableCheckout: {0}", object)); //NOI18N
+               }
+
+               // Securely cast it
+               WrapableCheckout checkout = (WrapableCheckout) object;
+
+               // Get customer and list from it
+               Customer customer = checkout.getCustomer();
+               List<AddableBasketItem> orderedItems = checkout.getList();
+
+               // Debug message
+               this.loggerBeanLocal.logDebug(MessageFormat.format("onMessage: customerInstance={0},itemList={1}", customer, orderedItems)); //NOI18N
+
+               // Check both on null
+               if (null == customer) {
+                       // customer is null
+                       throw new NullPointerException("customer is null"); //NOI18N
+               } else if (null == orderedItems) {
+                       // list is null
+                       throw new NullPointerException("list is null"); //NOI18N
+               }
+
+               try {
+                       // Is the customer already registered?
+                       if (this.customerBean.isRegistered(customer)) {
+                               // Already registered, so get all data
+                               customer = this.customerBean.fillCustomerData(customer);
+                       } else {
+                               // Register customer first, this generates a customer number
+                               customer = this.customerBean.registerCustomer(customer);
+                       }
+               } catch (final CustomerAlreadyRegisteredException ex) {
+                       // Log exception and abort
+                       this.loggerBeanLocal.logException(ex);
+                       return;
+               }
+
+               // Is the instance set?
+               if (null == customer) {
+                       // Customer is null
+                       throw new NullPointerException("customer is null"); //NOI18N
+               }
+
+               // Make sure the number has been regenerated
+               if (customer.getCustomerNumber() == null) {
+                       // Not assigned
+                       throw new NullPointerException(MessageFormat.format("registerCustomer() did not create a custome number: customerInstance={0}", customer)); //NOI18N
+               }
+
+               // Now add the ordered item list
+               String accessKey = this.basketBean.registerItems(customer, orderedItems);
+
+               // Debug message
+               this.loggerBeanLocal.logDebug(MessageFormat.format("onMessage: accessKey={0}", accessKey)); //NOI18N
+
+               // Should not be null
+               if (null == accessKey) {
+                       // Abort here
+                       throw new NullPointerException("accessKey is null"); //NOI18N
+               }
+
+               // Set access key and customer
+               this.receiptBean.setAccessKey(accessKey);
+               this.receiptBean.setCustomer(customer);
+
+               // Trace message
+               this.loggerBeanLocal.logTrace("onMessage: EXIT!"); //NOI18N
+       }
+
+}
diff --git a/src/java/org/mxchange/pizzaapplication/model/customer/ShopCustomerSessionBean.java b/src/java/org/mxchange/pizzaapplication/model/customer/ShopCustomerSessionBean.java
deleted file mode 100644 (file)
index b5be173..0000000
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- * Copyright (C) 2016, 2017 Roland Häder
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-package org.mxchange.pizzaapplication.model.customer;
-
-import java.text.MessageFormat;
-import java.util.GregorianCalendar;
-import java.util.Locale;
-import java.util.MissingResourceException;
-import java.util.ResourceBundle;
-import javax.ejb.Stateless;
-import javax.faces.application.FacesMessage;
-import javax.faces.context.FacesContext;
-import javax.persistence.EntityNotFoundException;
-import org.mxchange.jcoreee.database.BaseDatabaseBean;
-import org.mxchange.jcustomercore.exceptions.CustomerAlreadyRegisteredException;
-import org.mxchange.jcustomercore.exceptions.CustomerNotFoundException;
-import org.mxchange.jcustomercore.model.customer.Customer;
-import org.mxchange.jcustomercore.model.customer.CustomerSessionBeanRemote;
-
-/**
- * A customer bean which hides the customer instance
- * <p>
- * @author Roland Häder<roland@mxchange.org>
- */
-@Stateless (name = "shop_customer", description = "A bean handling the customer data")
-public abstract class ShopCustomerSessionBean extends BaseDatabaseBean implements CustomerSessionBeanRemote {
-
-       /**
-        * Serial number
-        */
-       private static final long serialVersionUID = 542_145_347_916L;
-
-       /**
-        * Default constructor
-        */
-       public ShopCustomerSessionBean () {
-               // Call super constructor
-               super();
-       }
-
-       @Override
-       public Customer fillCustomerData (final Customer customer) {
-               // Trace message
-               this.getLoggerBeanLocal().logTrace(MessageFormat.format("fillCustomerData: customer={0} - CALLED!", customer)); //NOI18N
-
-               // customer should not be null
-               if (null == customer) {
-                       // Abort here
-                       throw new NullPointerException("customer is null"); //NOI18N
-               }
-
-               // Try it
-               try {
-                       // Try to locate it
-                       Customer cat = this.getEntityManager().getReference(Customer.class, customer);
-
-                       // Copy all data
-                       customer.copyAll(cat);
-               } catch (final EntityNotFoundException ex) {
-                       // Log it
-                       this.getLoggerBeanLocal().logException(ex);
-
-                       // Return null
-                       return null;
-               }
-
-               // Trace message
-               this.getLoggerBeanLocal().logTrace(MessageFormat.format("fillCustomerData: customer={0} - EXIT!", customer)); //NOI18N
-
-               // Return prepared instance
-               return customer;
-       }
-
-       @Override
-       public Customer findCustomerById (final Long customerId) throws CustomerNotFoundException {
-               throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
-       }
-
-       @Override
-       public boolean isRegistered (final Customer customer) {
-               // Trace message
-               this.getLoggerBeanLocal().logTrace(MessageFormat.format("isRegistered: customer={0} - CALLED!", customer)); //NOI18N
-
-               // customer should not be null
-               if (null == customer) {
-                       // Abort here
-                       throw new NullPointerException("customer is null"); //NOI18N
-               }
-
-               // Try this
-               try {
-                       Customer c = this.getEntityManager().getReference(Customer.class, customer);
-               } catch (final EntityNotFoundException ex) {
-                       // Log it
-                       this.getLoggerBeanLocal().logException(ex);
-
-                       // Did not finish
-                       return false;
-               }
-
-               // Found it
-               return true;
-       }
-
-       @Override
-       public Customer registerCustomer (final Customer customer) throws CustomerAlreadyRegisteredException {
-               // Trace message
-               this.getLoggerBeanLocal().logTrace(MessageFormat.format("registerCustomer: customer={0} - CALLED!", customer)); //NOI18N
-
-               // customer should not be null
-               if (null == customer) {
-                       // Abort here
-                       throw new NullPointerException("customer is null"); //NOI18N
-               }
-
-               // Is the customer registered?
-               if (this.isRegistered(customer)) {
-                       // Already registered
-                       throw new CustomerAlreadyRegisteredException(customer);
-               }
-
-               // Debug message
-               this.getLoggerBeanLocal().logDebug(MessageFormat.format("registerCustomer: Preparing statement for customer={0}", customer)); //NOI18N
-
-               // Set creation timestamp
-               customer.setCustomerCreated(new GregorianCalendar());
-
-               // Try to persist it
-               this.getEntityManager().persist(customer);
-
-               // Flush it as the id might be needed
-               this.getEntityManager().flush();
-
-               // Debug message
-               this.getLoggerBeanLocal().logDebug(MessageFormat.format("registerCustomer: customer.id={0}", customer.getCustomerId())); //NOI18N
-
-               // Trace message
-               this.getLoggerBeanLocal().logTrace(MessageFormat.format("registerCustomer: customer={0} - CALLED!", customer)); //NOI18N
-
-               // Return prepared instance
-               return customer;
-       }
-
-       /**
-        * Returns given property key or throws an exception if not found.
-        * <p>
-        * @param parameterKey Property key
-        * <p>
-        * @return Property value
-        * <p>
-        * @throws NullPointerException If given key is not found
-        * @throws NumberFormatException If no number is given in context parameter
-        */
-       protected int getIntegerContextParameter (final String parameterKey) throws NullPointerException, NumberFormatException {
-               // Get context parameter
-               Integer contextValue = Integer.parseInt(this.getStringContextParameter(parameterKey));
-               // Return it
-               return contextValue;
-       }
-
-       /**
-        * Returns given property key or throws an exception if not found.
-        * <p>
-        * @param parameterKey Property key
-        * <p>
-        * @return Property value
-        * <p>
-        * @throws NullPointerException If given key is not found
-        */
-       protected String getStringContextParameter (final String parameterKey) throws NullPointerException {
-               // Get context parameter
-               String contextValue = FacesContext.getCurrentInstance().getExternalContext().getInitParameter(parameterKey);
-               // Is it null?
-               if (null == contextValue) {
-                       // Throw NPE
-                       throw new NullPointerException(MessageFormat.format("parameterKey={0} is not set.", parameterKey)); //NOI18N
-               }
-               // Return it
-               return contextValue;
-       }
-
-       /**
-        * Checks whether debug mode is enabled for given controller
-        * <p>
-        * @param controllerName Name of controller
-        * <p>
-        * @return Whether debug mode is enabled
-        */
-       protected boolean isDebugModeEnabled (final String controllerName) {
-               // Parameters should be valid
-               if (null == controllerName) {
-                       // Throw NPE
-                       throw new NullPointerException("controllerName is null"); //NOI18N
-               } else if (controllerName.isEmpty()) {
-                       // Is empty
-                       throw new IllegalArgumentException("controllerName is empty"); //NOI18N
-               }
-               // Try to get context parameter
-               String contextParameter = this.getStringContextParameter(String.format("is_debug_%s_enabled", controllerName)); //NOI18N
-               // Is it set and true?
-               boolean isEnabled = Boolean.parseBoolean(contextParameter) == Boolean.TRUE;
-               // Return it
-               return isEnabled;
-       }
-
-       /**
-        * Loads resource bundle for given locale. This must be implemented per
-        * project so all projects can still customize their methods. Calling
-        * ResourceBundleloadBundle() in this class means that also the bundle files
-        * must be present here.
-        * <p>
-        * @param locale Locale from e.g. FacesContext
-        * <p>
-        * @return Initialized and loaded resource bundle
-        */
-       protected abstract ResourceBundle loadResourceBundle (final Locale locale);
-
-       /**
-        * Shows a faces message for given causing exception. The message from the
-        * exception is being inserted into the message.
-        * <p>
-        * @param clientId Client id to send message to
-        * @param cause    Causing exception
-        */
-       protected void showFacesMessage (final String clientId, final Throwable cause) {
-               // Get context and add message
-               this.showFacesMessage(clientId, cause.getMessage());
-       }
-
-       /**
-        * Shows a faces message with given message (i18n) key.
-        * <p>
-        * @param clientId Client id to send message to
-        * @param i18nKey  Message key
-        * <p>
-        * @throws NullPointerException If clientId or i18nKey is null
-        * @throws IllegalArgumentException If clientId or i18nKey is empty
-        */
-       protected void showFacesMessage (final String clientId, final String i18nKey) throws NullPointerException, IllegalArgumentException {
-               // Both parameter must be valid
-               if (null == clientId) {
-                       // Throw NPE
-                       throw new NullPointerException("clientId is null"); //NOI18N
-               } else if (clientId.isEmpty()) {
-                       // Is empty
-                       throw new IllegalArgumentException("clientId is null"); //NOI18N
-               } else if (null == i18nKey) {
-                       // Throw NPE
-                       throw new NullPointerException("i18nKey is null"); //NOI18N
-               } else if (i18nKey.isEmpty()) {
-                       // Is empty
-                       throw new IllegalArgumentException("i18nKey is null"); //NOI18N
-               }
-               // Get current locale
-               Locale locale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
-               // Get bundle bundle
-               ResourceBundle bundle = this.loadResourceBundle(locale);
-               // Default is i18nKey
-               String message = MessageFormat.format("!{0}!", i18nKey); //NOI18N
-               // Try it
-               try {
-                       // Get message
-                       message = bundle.getString(i18nKey);
-               } catch (final MissingResourceException ex) {
-                       // Did not find it, ignored
-               }
-               // Get context and add message
-               FacesContext.getCurrentInstance().addMessage(clientId, new FacesMessage(message));
-       }
-
-}
diff --git a/src/java/org/mxchange/pizzaapplication/model/product/AdminProductSessionBean.java b/src/java/org/mxchange/pizzaapplication/model/product/AdminProductSessionBean.java
deleted file mode 100644 (file)
index d584147..0000000
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * Copyright (C) 2016, 2017 Roland Häder
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-package org.mxchange.pizzaapplication.model.product;
-
-import java.text.MessageFormat;
-import java.util.List;
-import java.util.Locale;
-import java.util.MissingResourceException;
-import java.util.ResourceBundle;
-import javax.ejb.Stateless;
-import javax.faces.application.FacesMessage;
-import javax.faces.context.FacesContext;
-import javax.persistence.EntityExistsException;
-import javax.persistence.EntityNotFoundException;
-import javax.persistence.NoResultException;
-import javax.persistence.Query;
-import org.mxchange.jcoreee.database.BaseDatabaseBean;
-import org.mxchange.jproduct.exceptions.CannotAddProductException;
-import org.mxchange.jproduct.exceptions.ProductTitleAlreadyUsedException;
-import org.mxchange.jproduct.model.product.GenericProduct;
-import org.mxchange.jproduct.model.product.Product;
-import org.mxchange.jshopcore.model.product.AdminProductSessionBeanRemote;
-
-/**
- * A session-scoped bean for non-administrative roles for products
- * <p>
- * @author Roland Häder<roland@mxchange.org>
- */
-@Stateless (name = "admin_product", description = "An administrative bean handling products")
-public abstract class AdminProductSessionBean extends BaseDatabaseBean implements AdminProductSessionBeanRemote {
-
-       /**
-        * Serial number
-        */
-       private static final long serialVersionUID = 65_173_487_394_812L;
-
-       /**
-        * Default constructor
-        */
-       public AdminProductSessionBean () {
-               // Call super constructor
-               super();
-       }
-
-       @Override
-       public Product doAdminAddProduct (final Product product) throws ProductTitleAlreadyUsedException, CannotAddProductException {
-               // Trace message
-               this.getLoggerBeanLocal().logTrace(MessageFormat.format("doAdminAddProduct: product={0} - CALLED!", product)); //NOI18N
-
-               // Check if product's title is used
-               if (null == product) {
-                       // product is null
-                       throw new NullPointerException("product is null"); //NOI18N
-               } else if (this.getEntityManager() == null) {
-                       // Connection is not there
-                       throw new NullPointerException("connection is null"); //NOI18N
-               } else if (this.isProductTitleUsed(product)) {
-                       // Throw exception
-                       throw new ProductTitleAlreadyUsedException(product);
-               }
-
-               try {
-                       // Persist it
-                       this.getEntityManager().persist(product);
-
-                       // Flush it as the id might be needed immediately
-                       this.getEntityManager().flush();
-               } catch (final EntityExistsException ex) {
-                       // Continue to throw
-                       throw new CannotAddProductException(ex);
-               }
-
-               // Trace message
-               this.getLoggerBeanLocal().logTrace(MessageFormat.format("doAdminAddProduct: product={0} - EXIT!", product)); //NOI18N
-
-               // Return it
-               return product;
-       }
-
-       @Override
-       @SuppressWarnings ("unchecked")
-       public List<Product> getAllProducts () {
-               // Trace message
-               this.getLoggerBeanLocal().logTrace("getAllProducts: CALLED!"); //NOI18N
-
-               // The connection must be there
-               if (this.getEntityManager() == null) {
-                       // Connection is not there
-                       throw new NullPointerException("connection is null"); //NOI18N
-               }
-
-               // Create statement
-               Query query = this.getEntityManager().createQuery("SELECT p FROM products AS p ORDER BY p.productId ASC", GenericProduct.class); //NOI18N
-
-               // Get list
-               List<Product> list = query.getResultList();
-
-               // Trace message
-               this.getLoggerBeanLocal().logTrace(MessageFormat.format("getAllProducts: list({0})={1} - EXIT!", list.size(), list)); //NOI18N
-
-               // Return it
-               return list;
-       }
-
-       /**
-        * Checks if the product's title has already been used as they need to be
-        * unique. This method works case-insensitive. Any spaces, new-line,
-        * carriage-return or tabulator characters are trimmed away. If the title
-        * has been used already, for performance reasons, the whole data is set in
-        * the product object.
-        * <p>
-        * @param product Product instance
-        * <p>
-        * @return Whether the product's title has been used
-        */
-       private boolean isProductTitleUsed (final Product product) {
-               // Trace message
-               this.getLoggerBeanLocal().logTrace(MessageFormat.format("isProductTitleUsed: Product={0} - CALLED!", product)); //NOI18N
-
-               // The connection must be there
-               if (null == product) {
-                       // product is null
-                       throw new NullPointerException("product is null"); //NOI18N
-               } else if (this.getEntityManager() == null) {
-                       // Connection is not there
-                       throw new NullPointerException("connection is null"); //NOI18N
-               }
-
-               // Default is not found
-               boolean isUsed = false;
-
-               // Try to locate it
-               try {
-                       // Get query instance
-                       Query query = this.getEntityManager().createQuery("SELECT p FROM products AS p WHERE LOWER(p.productTitle) = LOWER(:param)", GenericProduct.class); //NOI18N
-                       query.setParameter("param", product.getProductTitle()); //NOI18N
-                       Product pro = (Product) query.getSingleResult();
-
-                       // Is found, so copy the object
-                       product.copyAll(pro);
-
-                       // Mark as found
-                       isUsed = true;
-               } catch (final EntityNotFoundException | NoResultException e) {
-                       // Not found
-                       this.getLoggerBeanLocal().logWarning(e.getMessage());
-               }
-
-               // Trace message
-               this.getLoggerBeanLocal().logTrace(MessageFormat.format("isProductTitleUsed: isUsed={0} - EXIT!", isUsed)); //NOI18N
-
-               // Return it
-               return isUsed;
-       }
-
-       /**
-        * Returns given property key or throws an exception if not found.
-        * <p>
-        * @param parameterKey Property key
-        * <p>
-        * @return Property value
-        * <p>
-        * @throws NullPointerException If given key is not found
-        * @throws NumberFormatException If no number is given in context parameter
-        */
-       protected int getIntegerContextParameter (final String parameterKey) throws NullPointerException, NumberFormatException {
-               // Get context parameter
-               Integer contextValue = Integer.parseInt(this.getStringContextParameter(parameterKey));
-               // Return it
-               return contextValue;
-       }
-
-       /**
-        * Returns given property key or throws an exception if not found.
-        * <p>
-        * @param parameterKey Property key
-        * <p>
-        * @return Property value
-        * <p>
-        * @throws NullPointerException If given key is not found
-        */
-       protected String getStringContextParameter (final String parameterKey) throws NullPointerException {
-               // Get context parameter
-               String contextValue = FacesContext.getCurrentInstance().getExternalContext().getInitParameter(parameterKey);
-               // Is it null?
-               if (null == contextValue) {
-                       // Throw NPE
-                       throw new NullPointerException(MessageFormat.format("parameterKey={0} is not set.", parameterKey)); //NOI18N
-               }
-               // Return it
-               return contextValue;
-       }
-
-       /**
-        * Checks whether debug mode is enabled for given controller
-        * <p>
-        * @param controllerName Name of controller
-        * <p>
-        * @return Whether debug mode is enabled
-        */
-       protected boolean isDebugModeEnabled (final String controllerName) {
-               // Parameters should be valid
-               if (null == controllerName) {
-                       // Throw NPE
-                       throw new NullPointerException("controllerName is null"); //NOI18N
-               } else if (controllerName.isEmpty()) {
-                       // Is empty
-                       throw new IllegalArgumentException("controllerName is empty"); //NOI18N
-               }
-               // Try to get context parameter
-               String contextParameter = this.getStringContextParameter(String.format("is_debug_%s_enabled", controllerName)); //NOI18N
-               // Is it set and true?
-               boolean isEnabled = Boolean.parseBoolean(contextParameter) == Boolean.TRUE;
-               // Return it
-               return isEnabled;
-       }
-
-       /**
-        * Loads resource bundle for given locale. This must be implemented per
-        * project so all projects can still customize their methods. Calling
-        * ResourceBundleloadBundle() in this class means that also the bundle files
-        * must be present here.
-        * <p>
-        * @param locale Locale from e.g. FacesContext
-        * <p>
-        * @return Initialized and loaded resource bundle
-        */
-       protected abstract ResourceBundle loadResourceBundle (final Locale locale);
-
-       /**
-        * Shows a faces message for given causing exception. The message from the
-        * exception is being inserted into the message.
-        * <p>
-        * @param clientId Client id to send message to
-        * @param cause    Causing exception
-        */
-       protected void showFacesMessage (final String clientId, final Throwable cause) {
-               // Get context and add message
-               this.showFacesMessage(clientId, cause.getMessage());
-       }
-
-       /**
-        * Shows a faces message with given message (i18n) key.
-        * <p>
-        * @param clientId Client id to send message to
-        * @param i18nKey  Message key
-        * <p>
-        * @throws NullPointerException If clientId or i18nKey is null
-        * @throws IllegalArgumentException If clientId or i18nKey is empty
-        */
-       protected void showFacesMessage (final String clientId, final String i18nKey) throws NullPointerException, IllegalArgumentException {
-               // Both parameter must be valid
-               if (null == clientId) {
-                       // Throw NPE
-                       throw new NullPointerException("clientId is null"); //NOI18N
-               } else if (clientId.isEmpty()) {
-                       // Is empty
-                       throw new IllegalArgumentException("clientId is null"); //NOI18N
-               } else if (null == i18nKey) {
-                       // Throw NPE
-                       throw new NullPointerException("i18nKey is null"); //NOI18N
-               } else if (i18nKey.isEmpty()) {
-                       // Is empty
-                       throw new IllegalArgumentException("i18nKey is null"); //NOI18N
-               }
-               // Get current locale
-               Locale locale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
-               // Get bundle bundle
-               ResourceBundle bundle = this.loadResourceBundle(locale);
-               // Default is i18nKey
-               String message = MessageFormat.format("!{0}!", i18nKey); //NOI18N
-               // Try it
-               try {
-                       // Get message
-                       message = bundle.getString(i18nKey);
-               } catch (final MissingResourceException ex) {
-                       // Did not find it, ignored
-               }
-               // Get context and add message
-               FacesContext.getCurrentInstance().addMessage(clientId, new FacesMessage(message));
-       }
-
-}
diff --git a/src/java/org/mxchange/pizzaapplication/model/product/PizzaAdminProductSessionBean.java b/src/java/org/mxchange/pizzaapplication/model/product/PizzaAdminProductSessionBean.java
new file mode 100644 (file)
index 0000000..389885c
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2016, 2017 Roland Häder
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.mxchange.pizzaapplication.model.product;
+
+import java.text.MessageFormat;
+import java.util.List;
+import javax.ejb.Stateless;
+import javax.persistence.EntityExistsException;
+import javax.persistence.EntityNotFoundException;
+import javax.persistence.NoResultException;
+import javax.persistence.Query;
+import org.mxchange.jcoreee.database.BaseDatabaseBean;
+import org.mxchange.jproduct.exceptions.CannotAddProductException;
+import org.mxchange.jproduct.exceptions.ProductTitleAlreadyUsedException;
+import org.mxchange.jproduct.model.product.GenericProduct;
+import org.mxchange.jproduct.model.product.Product;
+import org.mxchange.jshopcore.model.product.AdminProductSessionBeanRemote;
+
+/**
+ * A session-scoped bean for non-administrative roles for products
+ * <p>
+ * @author Roland Häder<roland@mxchange.org>
+ */
+@Stateless (name = "admin_product", description = "An administrative bean handling products")
+public class PizzaAdminProductSessionBean extends BaseDatabaseBean implements AdminProductSessionBeanRemote {
+
+       /**
+        * Serial number
+        */
+       private static final long serialVersionUID = 65_173_487_394_812L;
+
+       /**
+        * Default constructor
+        */
+       public PizzaAdminProductSessionBean () {
+               // Call super constructor
+               super();
+       }
+
+       @Override
+       public Product doAdminAddProduct (final Product product) throws ProductTitleAlreadyUsedException, CannotAddProductException {
+               // Trace message
+               this.getLoggerBeanLocal().logTrace(MessageFormat.format("doAdminAddProduct: product={0} - CALLED!", product)); //NOI18N
+
+               // Check if product's title is used
+               if (null == product) {
+                       // product is null
+                       throw new NullPointerException("product is null"); //NOI18N
+               } else if (this.getEntityManager() == null) {
+                       // Connection is not there
+                       throw new NullPointerException("connection is null"); //NOI18N
+               } else if (this.isProductTitleUsed(product)) {
+                       // Throw exception
+                       throw new ProductTitleAlreadyUsedException(product);
+               }
+
+               try {
+                       // Persist it
+                       this.getEntityManager().persist(product);
+
+                       // Flush it as the id might be needed immediately
+                       this.getEntityManager().flush();
+               } catch (final EntityExistsException ex) {
+                       // Continue to throw
+                       throw new CannotAddProductException(ex);
+               }
+
+               // Trace message
+               this.getLoggerBeanLocal().logTrace(MessageFormat.format("doAdminAddProduct: product={0} - EXIT!", product)); //NOI18N
+
+               // Return it
+               return product;
+       }
+
+       @Override
+       @SuppressWarnings ("unchecked")
+       public List<Product> getAllProducts () {
+               // Trace message
+               this.getLoggerBeanLocal().logTrace("getAllProducts: CALLED!"); //NOI18N
+
+               // The connection must be there
+               if (this.getEntityManager() == null) {
+                       // Connection is not there
+                       throw new NullPointerException("connection is null"); //NOI18N
+               }
+
+               // Create statement
+               Query query = this.getEntityManager().createQuery("SELECT p FROM products AS p ORDER BY p.productId ASC", GenericProduct.class); //NOI18N
+
+               // Get list
+               List<Product> list = query.getResultList();
+
+               // Trace message
+               this.getLoggerBeanLocal().logTrace(MessageFormat.format("getAllProducts: list({0})={1} - EXIT!", list.size(), list)); //NOI18N
+
+               // Return it
+               return list;
+       }
+
+       /**
+        * Checks if the product's title has already been used as they need to be
+        * unique. This method works case-insensitive. Any spaces, new-line,
+        * carriage-return or tabulator characters are trimmed away. If the title
+        * has been used already, for performance reasons, the whole data is set in
+        * the product object.
+        * <p>
+        * @param product Product instance
+        * <p>
+        * @return Whether the product's title has been used
+        */
+       private boolean isProductTitleUsed (final Product product) {
+               // Trace message
+               this.getLoggerBeanLocal().logTrace(MessageFormat.format("isProductTitleUsed: Product={0} - CALLED!", product)); //NOI18N
+
+               // The connection must be there
+               if (null == product) {
+                       // product is null
+                       throw new NullPointerException("product is null"); //NOI18N
+               } else if (this.getEntityManager() == null) {
+                       // Connection is not there
+                       throw new NullPointerException("connection is null"); //NOI18N
+               }
+
+               // Default is not found
+               boolean isUsed = false;
+
+               // Try to locate it
+               try {
+                       // Get query instance
+                       Query query = this.getEntityManager().createQuery("SELECT p FROM products AS p WHERE LOWER(p.productTitle) = LOWER(:param)", GenericProduct.class); //NOI18N
+                       query.setParameter("param", product.getProductTitle()); //NOI18N
+                       Product pro = (Product) query.getSingleResult();
+
+                       // Is found, so copy the object
+                       product.copyAll(pro);
+
+                       // Mark as found
+                       isUsed = true;
+               } catch (final EntityNotFoundException | NoResultException e) {
+                       // Not found
+                       this.getLoggerBeanLocal().logWarning(e.getMessage());
+               }
+
+               // Trace message
+               this.getLoggerBeanLocal().logTrace(MessageFormat.format("isProductTitleUsed: isUsed={0} - EXIT!", isUsed)); //NOI18N
+
+               // Return it
+               return isUsed;
+       }
+
+}
diff --git a/src/java/org/mxchange/pizzaapplication/model/product/PizzaProductSessionBean.java b/src/java/org/mxchange/pizzaapplication/model/product/PizzaProductSessionBean.java
new file mode 100644 (file)
index 0000000..241176d
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2016, 2017 Roland Häder
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.mxchange.pizzaapplication.model.product;
+
+import java.text.MessageFormat;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import javax.ejb.EJB;
+import javax.ejb.Stateless;
+import org.mxchange.jcoreee.database.BaseDatabaseBean;
+import org.mxchange.jproduct.model.product.Product;
+import org.mxchange.jshopcore.model.product.AdminProductSessionBeanRemote;
+import org.mxchange.jshopcore.model.product.ProductSessionBeanRemote;
+
+/**
+ * A session-scoped bean for non-administrative roles for products
+ * <p>
+ * @author Roland Häder<roland@mxchange.org>
+ */
+@Stateless (name = "product", description = "A bean handling products for all others (non-admin)")
+public class PizzaProductSessionBean extends BaseDatabaseBean implements ProductSessionBeanRemote {
+
+       /**
+        * Serial number
+        */
+       private static final long serialVersionUID = 65_173_487_394_812L;
+
+       /**
+        * Administrative bean
+        */
+       @EJB
+       private AdminProductSessionBeanRemote productBean;
+
+       /**
+        * Default constructor
+        */
+       public PizzaProductSessionBean () {
+               // Call super constructor
+               super();
+       }
+
+       @Override
+       public List<Product> getAvailableProducts () {
+               // Trace message
+               this.getLoggerBeanLocal().logTrace("getAvailableProducts: CALLED!"); //NOI18N
+
+               // The connection must be there
+               if (this.getEntityManager() == null) {
+                       // Connection is not there
+                       throw new NullPointerException("connection is null"); //NOI18N
+               }
+
+               // Get all products
+               List<Product> allProducts = this.productBean.getAllProducts();
+
+               // Trace message
+               this.getLoggerBeanLocal().logTrace(MessageFormat.format("getAvailableProducts: allProducts({0})={1}", allProducts.size(), allProducts)); //NOI18N
+
+               // Init deque
+               List<Product> deque = new LinkedList<>();
+
+               // Get iterator
+               Iterator<Product> iterator = allProducts.iterator();
+
+               // Walk through all and add only available
+               while (iterator.hasNext()) {
+                       // Get element
+                       Product localProduct = iterator.next();
+
+                       // Debug message
+                       this.getLoggerBeanLocal().logDebug(MessageFormat.format("getAvailableProducts: localProduct={0}", localProduct)); //NOI18N
+
+                       // Is this available?
+                       if (localProduct.getProductAvailability()) {
+                               // Debug message
+                               this.getLoggerBeanLocal().logDebug(MessageFormat.format("getAvailableProducts: localProduct={0} - ADDED!", localProduct)); //NOI18N
+
+                               // Add it
+                               deque.add(localProduct);
+                       }
+               }
+
+               // Trace message
+               this.getLoggerBeanLocal().logTrace(MessageFormat.format("getAvailableProducts: deque({0})={1} - EXIT!", deque.size(), deque)); //NOI18N
+
+               // Return it
+               return deque;
+       }
+
+}
diff --git a/src/java/org/mxchange/pizzaapplication/model/product/ProductSessionBean.java b/src/java/org/mxchange/pizzaapplication/model/product/ProductSessionBean.java
deleted file mode 100644 (file)
index 96fdb09..0000000
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * Copyright (C) 2016, 2017 Roland Häder
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-package org.mxchange.pizzaapplication.model.product;
-
-import java.text.MessageFormat;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Locale;
-import java.util.MissingResourceException;
-import java.util.ResourceBundle;
-import javax.ejb.EJB;
-import javax.ejb.Stateless;
-import javax.faces.application.FacesMessage;
-import javax.faces.context.FacesContext;
-import org.mxchange.jcoreee.database.BaseDatabaseBean;
-import org.mxchange.jproduct.model.product.Product;
-import org.mxchange.jshopcore.model.product.AdminProductSessionBeanRemote;
-import org.mxchange.jshopcore.model.product.ProductSessionBeanRemote;
-
-/**
- * A session-scoped bean for non-administrative roles for products
- * <p>
- * @author Roland Häder<roland@mxchange.org>
- */
-@Stateless (name = "product", description = "A bean handling products for all others (non-admin)")
-public abstract class ProductSessionBean extends BaseDatabaseBean implements ProductSessionBeanRemote {
-
-       /**
-        * Serial number
-        */
-       private static final long serialVersionUID = 65_173_487_394_812L;
-
-       /**
-        * Administrative bean
-        */
-       @EJB
-       private AdminProductSessionBeanRemote productBean;
-
-       /**
-        * Default constructor
-        */
-       public ProductSessionBean () {
-               // Call super constructor
-               super();
-       }
-
-       @Override
-       public List<Product> getAvailableProducts () {
-               // Trace message
-               this.getLoggerBeanLocal().logTrace("getAvailableProducts: CALLED!"); //NOI18N
-
-               // The connection must be there
-               if (this.getEntityManager() == null) {
-                       // Connection is not there
-                       throw new NullPointerException("connection is null"); //NOI18N
-               }
-
-               // Get all products
-               List<Product> allProducts = this.productBean.getAllProducts();
-
-               // Trace message
-               this.getLoggerBeanLocal().logTrace(MessageFormat.format("getAvailableProducts: allProducts({0})={1}", allProducts.size(), allProducts)); //NOI18N
-
-               // Init deque
-               List<Product> deque = new LinkedList<>();
-
-               // Get iterator
-               Iterator<Product> iterator = allProducts.iterator();
-
-               // Walk through all and add only available
-               while (iterator.hasNext()) {
-                       // Get element
-                       Product localProduct = iterator.next();
-
-                       // Debug message
-                       this.getLoggerBeanLocal().logDebug(MessageFormat.format("getAvailableProducts: localProduct={0}", localProduct)); //NOI18N
-
-                       // Is this available?
-                       if (localProduct.getProductAvailability()) {
-                               // Debug message
-                               this.getLoggerBeanLocal().logDebug(MessageFormat.format("getAvailableProducts: localProduct={0} - ADDED!", localProduct)); //NOI18N
-
-                               // Add it
-                               deque.add(localProduct);
-                       }
-               }
-
-               // Trace message
-               this.getLoggerBeanLocal().logTrace(MessageFormat.format("getAvailableProducts: deque({0})={1} - EXIT!", deque.size(), deque)); //NOI18N
-
-               // Return it
-               return deque;
-       }
-
-       /**
-        * Returns given property key or throws an exception if not found.
-        * <p>
-        * @param parameterKey Property key
-        * <p>
-        * @return Property value
-        * <p>
-        * @throws NullPointerException If given key is not found
-        * @throws NumberFormatException If no number is given in context parameter
-        */
-       protected int getIntegerContextParameter (final String parameterKey) throws NullPointerException, NumberFormatException {
-               // Get context parameter
-               Integer contextValue = Integer.parseInt(this.getStringContextParameter(parameterKey));
-               // Return it
-               return contextValue;
-       }
-
-       /**
-        * Returns given property key or throws an exception if not found.
-        * <p>
-        * @param parameterKey Property key
-        * <p>
-        * @return Property value
-        * <p>
-        * @throws NullPointerException If given key is not found
-        */
-       protected String getStringContextParameter (final String parameterKey) throws NullPointerException {
-               // Get context parameter
-               String contextValue = FacesContext.getCurrentInstance().getExternalContext().getInitParameter(parameterKey);
-               // Is it null?
-               if (null == contextValue) {
-                       // Throw NPE
-                       throw new NullPointerException(MessageFormat.format("parameterKey={0} is not set.", parameterKey)); //NOI18N
-               }
-               // Return it
-               return contextValue;
-       }
-
-       /**
-        * Checks whether debug mode is enabled for given controller
-        * <p>
-        * @param controllerName Name of controller
-        * <p>
-        * @return Whether debug mode is enabled
-        */
-       protected boolean isDebugModeEnabled (final String controllerName) {
-               // Parameters should be valid
-               if (null == controllerName) {
-                       // Throw NPE
-                       throw new NullPointerException("controllerName is null"); //NOI18N
-               } else if (controllerName.isEmpty()) {
-                       // Is empty
-                       throw new IllegalArgumentException("controllerName is empty"); //NOI18N
-               }
-               // Try to get context parameter
-               String contextParameter = this.getStringContextParameter(String.format("is_debug_%s_enabled", controllerName)); //NOI18N
-               // Is it set and true?
-               boolean isEnabled = Boolean.parseBoolean(contextParameter) == Boolean.TRUE;
-               // Return it
-               return isEnabled;
-       }
-
-       /**
-        * Loads resource bundle for given locale. This must be implemented per
-        * project so all projects can still customize their methods. Calling
-        * ResourceBundleloadBundle() in this class means that also the bundle files
-        * must be present here.
-        * <p>
-        * @param locale Locale from e.g. FacesContext
-        * <p>
-        * @return Initialized and loaded resource bundle
-        */
-       protected abstract ResourceBundle loadResourceBundle (final Locale locale);
-
-       /**
-        * Shows a faces message for given causing exception. The message from the
-        * exception is being inserted into the message.
-        * <p>
-        * @param clientId Client id to send message to
-        * @param cause    Causing exception
-        */
-       protected void showFacesMessage (final String clientId, final Throwable cause) {
-               // Get context and add message
-               this.showFacesMessage(clientId, cause.getMessage());
-       }
-
-       /**
-        * Shows a faces message with given message (i18n) key.
-        * <p>
-        * @param clientId Client id to send message to
-        * @param i18nKey  Message key
-        * <p>
-        * @throws NullPointerException If clientId or i18nKey is null
-        * @throws IllegalArgumentException If clientId or i18nKey is empty
-        */
-       protected void showFacesMessage (final String clientId, final String i18nKey) throws NullPointerException, IllegalArgumentException {
-               // Both parameter must be valid
-               if (null == clientId) {
-                       // Throw NPE
-                       throw new NullPointerException("clientId is null"); //NOI18N
-               } else if (clientId.isEmpty()) {
-                       // Is empty
-                       throw new IllegalArgumentException("clientId is null"); //NOI18N
-               } else if (null == i18nKey) {
-                       // Throw NPE
-                       throw new NullPointerException("i18nKey is null"); //NOI18N
-               } else if (i18nKey.isEmpty()) {
-                       // Is empty
-                       throw new IllegalArgumentException("i18nKey is null"); //NOI18N
-               }
-               // Get current locale
-               Locale locale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
-               // Get bundle bundle
-               ResourceBundle bundle = this.loadResourceBundle(locale);
-               // Default is i18nKey
-               String message = MessageFormat.format("!{0}!", i18nKey); //NOI18N
-               // Try it
-               try {
-                       // Get message
-                       message = bundle.getString(i18nKey);
-               } catch (final MissingResourceException ex) {
-                       // Did not find it, ignored
-               }
-               // Get context and add message
-               FacesContext.getCurrentInstance().addMessage(clientId, new FacesMessage(message));
-       }
-
-}