You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@empire-db.apache.org by do...@apache.org on 2022/01/20 04:18:23 UTC
[empire-db] branch version3 updated: WebContext test
This is an automated email from the ASF dual-hosted git repository.
doebele pushed a commit to branch version3
in repository https://gitbox.apache.org/repos/asf/empire-db.git
The following commit(s) were added to refs/heads/version3 by this push:
new 6d7f6e0 WebContext test
6d7f6e0 is described below
commit 6d7f6e07fda5a87bfdb69d327da2ea44b5766de1
Author: Rainer Döbele <do...@apache.org>
AuthorDate: Thu Jan 20 05:18:20 2022 +0100
WebContext test
---
.../jsf2/websample/web/AppExceptionHandler.java | 208 +++++++++++++++++++++
.../websample/web/AppExceptionHandlerFactory.java | 29 +++
.../empire/jsf2/websample/web/SampleUser.java | 2 +-
.../websample/web/pages/EmployeeDetailPage.java | 10 +-
.../jsf2/websample/web/pages/EmployeeListPage.java | 1 -
.../src/main/webapp/WEB-INF/faces-config.xml | 4 +
.../org/apache/empire/jsf2/app/WebApplication.java | 52 ++++--
.../org/apache/empire/jsf2/app/WebDBContext.java | 44 ++++-
.../apache/empire/db/context/DBContextBase.java | 30 ++-
9 files changed, 347 insertions(+), 33 deletions(-)
diff --git a/empire-db-examples/empire-db-example-jsf2/src/main/java/org/apache/empire/jsf2/websample/web/AppExceptionHandler.java b/empire-db-examples/empire-db-example-jsf2/src/main/java/org/apache/empire/jsf2/websample/web/AppExceptionHandler.java
new file mode 100644
index 0000000..c6110bf
--- /dev/null
+++ b/empire-db-examples/empire-db-example-jsf2/src/main/java/org/apache/empire/jsf2/websample/web/AppExceptionHandler.java
@@ -0,0 +1,208 @@
+package org.apache.empire.jsf2.websample.web;
+
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.faces.FacesException;
+import javax.faces.application.FacesMessage;
+import javax.faces.context.ExceptionHandler;
+import javax.faces.context.ExceptionHandlerWrapper;
+import javax.faces.context.FacesContext;
+import javax.faces.event.ExceptionQueuedEvent;
+import javax.faces.event.ExceptionQueuedEventContext;
+
+import org.apache.empire.exceptions.EmpireException;
+import org.apache.empire.exceptions.InternalException;
+import org.apache.empire.jsf2.app.FacesUtils;
+import org.apache.empire.jsf2.app.TextResolver;
+import org.apache.empire.jsf2.app.WebApplication;
+import org.apache.empire.jsf2.websample.web.pages.SamplePages;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class AppExceptionHandler extends ExceptionHandlerWrapper
+{
+
+ private static final Logger log = LoggerFactory.getLogger(AppExceptionHandler.class);
+
+ private final ExceptionHandler wrapped;
+
+ public AppExceptionHandler(ExceptionHandler delegate)
+ {
+ // super(delegate);
+ this.wrapped = delegate;
+ }
+
+ @Override
+ public javax.faces.context.ExceptionHandler getWrapped()
+ {
+ return this.wrapped;
+ }
+
+ @Override
+ public void handle()
+ throws FacesException
+ {
+ // boolean redirectToErrorPage = false;
+ Throwable rootCause = null;
+ Iterator<ExceptionQueuedEvent> events = getUnhandledExceptionQueuedEvents().iterator();
+
+ // log each error
+ while (events.hasNext())
+ {
+ ExceptionQueuedEvent event = events.next();
+ // handle
+ try {
+
+ ExceptionQueuedEventContext source = (ExceptionQueuedEventContext) event.getSource();
+ FacesContext context = source.getContext();
+ Throwable t = source.getException();
+
+ // check t
+ if (t==null)
+ { log.error("Cannot handle exception. Exception not supplied with context!");
+ setErrorMessage(context, null);
+ continue;
+ }
+
+ // find root
+ rootCause = t.getCause();
+ // second option: getRootCause
+ if (rootCause == null)
+ { // get cause
+ rootCause = getRootCause(t);
+ }
+ // third option: use t
+ if (rootCause == null)
+ {
+ rootCause = t;
+ }
+
+ // Walk up the tree
+ while (true)
+ { // if its an empire-exception: game over
+ if (rootCause instanceof EmpireException)
+ break;
+ // has root cause
+ t = rootCause.getCause();
+ if (t==null)
+ break;
+ // yes, continue search
+ rootCause = t;
+ }
+
+ /*
+ if (rootCause instanceof org.icefaces.application.SessionExpiredException)
+ { // expired
+ log.info("Handling SessionExpiredException. No error message is set.");
+ continue;
+ }
+ */
+
+ // set message
+ String msg = "Handling exception of type "+rootCause.getClass().getSimpleName();
+ // log
+ // msg = appendSessionInfo(context, msg);
+ log.error(msg, rootCause);
+
+ // set message
+ if (!(rootCause instanceof EmpireException))
+ { // Wrap as internal exception
+ rootCause = new InternalException(rootCause);
+ }
+ setErrorMessage(context, rootCause);
+
+ } catch(Throwable t2) {
+ log.error("Failed to handle exception: "+t2.getMessage(), t2);
+ } finally {
+ events.remove();
+ }
+ }
+
+ // if an error has been found
+ /*
+ if (redirectToErrorPage)
+ {
+ HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
+ try
+ {
+ // put error to session map (will be cleared by ErrorPage)
+ if (rootCause != null)
+ {
+ FacesUtils.getFin2Session().setError(rootCause);
+ }
+ // redirect to error page
+ String errorPage = FacesUtils.getContextPath() + "/pages/error.iface";
+ Fin2ExceptionHandler.log.debug("Redirecting to error page at '" + errorPage + "'...");
+ FacesUtils.redirectDirectly(errorPage);
+ }
+ catch (Exception e)
+ {
+ Fin2ExceptionHandler.log.error("Error during exception handling.", e);
+ throw new FacesException(e);
+ }
+ }
+ */
+ // let next handler deal
+ getWrapped().handle();
+ }
+
+ /*
+ private String appendSessionInfo(FacesContext context, String msg)
+ {
+ // Provide session info
+ Fin2Session session = FinUtils.getFin2Session(context, false);
+ Fin2User user = (session!=null ? session.getUser() : null);
+ if (user!=null)
+ { // Add user information
+ String viewId;
+ if (context.getViewRoot()!=null)
+ viewId = context.getViewRoot().getViewId();
+ else {
+ viewId = "[NO VIEW]";
+ if (context.getExternalContext()!=null)
+ { // External Context
+ Object request = context.getExternalContext().getRequest();
+ if (request instanceof HttpServletRequest)
+ { // The HttpServletRequest Servlet Path
+ String path = ((HttpServletRequest)request).getServletPath();
+ viewId += " ("+String.valueOf(path)+")";
+ }
+ else if (request!=null)
+ viewId += " {"+request.getClass().getName()+"}";
+ }
+ }
+ // Message
+ msg += MessageFormat.format(" for User {0} of DUNS {1} on View {2}.", user.getUserId(), user.getDUNS(), viewId);
+ }
+ return msg;
+ }
+ */
+
+ private void setErrorMessage(FacesContext fContext, Throwable rootCause)
+ {
+ FacesMessage message = new FacesMessage();
+ message.setSeverity(FacesMessage.SEVERITY_ERROR);
+
+ Map<String, Object> sm = fContext.getExternalContext().getSessionMap();
+ if (sm.containsKey(SampleSession.MANAGED_BEAN_NAME))
+ {
+ TextResolver resolver = WebApplication.getInstance().getTextResolver(fContext);
+ if (rootCause instanceof Exception)
+ {
+ message.setSummary(resolver.getExceptionMessage((Exception)rootCause));
+ }
+ else
+ {
+ message.setSummary(resolver.resolveKey("global_general_error"));
+ }
+ // Add message
+ fContext.addMessage(null, message);
+ }
+ else
+ {
+ log.error("Unable to handle exception, redirecting to StartPage.", rootCause);
+ FacesUtils.redirectDirectly(fContext, SamplePages.LoginPage);
+ }
+ }
+}
diff --git a/empire-db-examples/empire-db-example-jsf2/src/main/java/org/apache/empire/jsf2/websample/web/AppExceptionHandlerFactory.java b/empire-db-examples/empire-db-example-jsf2/src/main/java/org/apache/empire/jsf2/websample/web/AppExceptionHandlerFactory.java
new file mode 100644
index 0000000..bfd6253
--- /dev/null
+++ b/empire-db-examples/empire-db-example-jsf2/src/main/java/org/apache/empire/jsf2/websample/web/AppExceptionHandlerFactory.java
@@ -0,0 +1,29 @@
+package org.apache.empire.jsf2.websample.web;
+
+import javax.faces.context.ExceptionHandler;
+import javax.faces.context.ExceptionHandlerFactory;
+
+/**
+ * AppExceptionHandlerFactory
+ */
+public class AppExceptionHandlerFactory extends ExceptionHandlerFactory
+{
+ ExceptionHandlerFactory delegateFactory;
+
+ public AppExceptionHandlerFactory(ExceptionHandlerFactory delegateFactory)
+ {
+ this.delegateFactory = delegateFactory;
+ }
+
+ @Override
+ public ExceptionHandlerFactory getWrapped()
+ {
+ return delegateFactory;
+ }
+
+ @Override
+ public ExceptionHandler getExceptionHandler()
+ {
+ return new AppExceptionHandler(getWrapped().getExceptionHandler());
+ }
+}
diff --git a/empire-db-examples/empire-db-example-jsf2/src/main/java/org/apache/empire/jsf2/websample/web/SampleUser.java b/empire-db-examples/empire-db-example-jsf2/src/main/java/org/apache/empire/jsf2/websample/web/SampleUser.java
index 686bb3c..99b2c16 100644
--- a/empire-db-examples/empire-db-example-jsf2/src/main/java/org/apache/empire/jsf2/websample/web/SampleUser.java
+++ b/empire-db-examples/empire-db-example-jsf2/src/main/java/org/apache/empire/jsf2/websample/web/SampleUser.java
@@ -26,7 +26,7 @@ public class SampleUser implements Serializable
private static final long serialVersionUID = 1L;
protected static final String MANAGED_BEAN_NAME = "sampleUser";
- private String userName = "";
+ private String userName = "test";
private String password = "";
private Locale language = SampleApplication.DEFAULT_LOCALE;
diff --git a/empire-db-examples/empire-db-example-jsf2/src/main/java/org/apache/empire/jsf2/websample/web/pages/EmployeeDetailPage.java b/empire-db-examples/empire-db-example-jsf2/src/main/java/org/apache/empire/jsf2/websample/web/pages/EmployeeDetailPage.java
index 7f91052..bdc1cb7 100644
--- a/empire-db-examples/empire-db-example-jsf2/src/main/java/org/apache/empire/jsf2/websample/web/pages/EmployeeDetailPage.java
+++ b/empire-db-examples/empire-db-example-jsf2/src/main/java/org/apache/empire/jsf2/websample/web/pages/EmployeeDetailPage.java
@@ -18,8 +18,6 @@
*/
package org.apache.empire.jsf2.websample.web.pages;
-import java.sql.Connection;
-
import org.apache.empire.jsf2.pageelements.RecordPageElement;
import org.apache.empire.jsf2.pages.PageOutcome;
import org.apache.empire.jsf2.websample.db.SampleDB;
@@ -102,7 +100,15 @@ public class EmployeeDetailPage extends SamplePage
public PageOutcome doSave()
{
+
getEmployeeRecord().update();
+
+ /* test transaction
+ SampleDB db = this.getDatabase();
+ if (getEmployeeRecord().isNull(db.T_EMPLOYEES.PHONE_NUMBER))
+ throw new MiscellaneousErrorException("Phone number must not be empty!");
+ */
+
return getParentOutcome(true);
}
diff --git a/empire-db-examples/empire-db-example-jsf2/src/main/java/org/apache/empire/jsf2/websample/web/pages/EmployeeListPage.java b/empire-db-examples/empire-db-example-jsf2/src/main/java/org/apache/empire/jsf2/websample/web/pages/EmployeeListPage.java
index 18af8d8..dcdf356 100644
--- a/empire-db-examples/empire-db-example-jsf2/src/main/java/org/apache/empire/jsf2/websample/web/pages/EmployeeListPage.java
+++ b/empire-db-examples/empire-db-example-jsf2/src/main/java/org/apache/empire/jsf2/websample/web/pages/EmployeeListPage.java
@@ -26,7 +26,6 @@ import java.util.Date;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.empire.commons.ObjectUtils;
import org.apache.empire.commons.Options;
-import org.apache.empire.data.DataType;
import org.apache.empire.db.DBColumn;
import org.apache.empire.db.DBColumnExpr;
import org.apache.empire.db.DBCommand;
diff --git a/empire-db-examples/empire-db-example-jsf2/src/main/webapp/WEB-INF/faces-config.xml b/empire-db-examples/empire-db-example-jsf2/src/main/webapp/WEB-INF/faces-config.xml
index 6e43a4e..2d6d4cc 100644
--- a/empire-db-examples/empire-db-example-jsf2/src/main/webapp/WEB-INF/faces-config.xml
+++ b/empire-db-examples/empire-db-example-jsf2/src/main/webapp/WEB-INF/faces-config.xml
@@ -14,6 +14,10 @@
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
version="2.0">
+ <factory>
+ <exception-handler-factory>org.apache.empire.jsf2.websample.web.AppExceptionHandlerFactory</exception-handler-factory>
+ </factory>
+
<application>
<!-- System event listener -->
<system-event-listener>
diff --git a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/app/WebApplication.java b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/app/WebApplication.java
index 4607a4d..d9948a3 100644
--- a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/app/WebApplication.java
+++ b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/app/WebApplication.java
@@ -45,6 +45,7 @@ import org.apache.empire.db.DBDatabase;
import org.apache.empire.exceptions.InternalException;
import org.apache.empire.exceptions.InvalidArgumentException;
import org.apache.empire.exceptions.NotSupportedException;
+import org.apache.empire.exceptions.UnexpectedReturnValueException;
import org.apache.empire.jsf2.controls.TextAreaInputControl;
import org.apache.empire.jsf2.controls.TextInputControl;
import org.apache.empire.jsf2.impl.FacesImplementation;
@@ -58,6 +59,8 @@ public abstract class WebApplication
private static final String CONNECTION_ATTRIBUTE = "dbConnections";
+ private static final String DB_CONTEXT_MAP = "dbContextMap";
+
public static String APPLICATION_BEAN_NAME = "webApplication";
protected TextResolver[] textResolvers = null;
@@ -453,28 +456,38 @@ public abstract class WebApplication
/**
* returns a connection for the current Request
*/
- public Connection getConnectionForRequest(FacesContext fc, DBDatabase db)
+ public Connection getConnectionForRequest(FacesContext fc, WebDBContext<? extends DBDatabase> context)
{
if (fc == null)
throw new InvalidArgumentException("FacesContext", fc);
- if (db == null)
- throw new InvalidArgumentException("DBDatabase", db);
+ if (context == null)
+ throw new InvalidArgumentException("context", context);
// Get Conneciton map
+ DBDatabase db = context.getDatabase();
@SuppressWarnings("unchecked")
Map<DBDatabase, Connection> connMap = (Map<DBDatabase, Connection>) FacesUtils.getRequestAttribute(fc, CONNECTION_ATTRIBUTE);
- if (connMap != null && connMap.containsKey(db))
- return connMap.get(db);
- // Pooled Connection
- Connection conn = getConnection(db);
- if (conn == null)
- return null;
- // Add to map
- if (connMap == null)
- {
- connMap = new HashMap<DBDatabase, Connection>();
+ if (connMap== null)
+ { connMap = new HashMap<DBDatabase, Connection>();
FacesUtils.setRequestAttribute(fc, CONNECTION_ATTRIBUTE, connMap);
}
- connMap.put(db, conn);
+ Connection conn = connMap.get(db);
+ if (conn==null)
+ { // Get Pooled Connection
+ conn = getConnection(db);
+ if (conn== null)
+ throw new UnexpectedReturnValueException(this, "getConnection");
+ // Add to map
+ connMap.put(db, conn);
+ }
+ // Store Context
+ @SuppressWarnings("unchecked")
+ Map<Integer, WebDBContext<? extends DBDatabase>> ctxMap = (Map<Integer, WebDBContext<? extends DBDatabase>>) FacesUtils.getRequestAttribute(fc, DB_CONTEXT_MAP);
+ if (ctxMap== null)
+ { ctxMap = new HashMap<Integer, WebDBContext<? extends DBDatabase>>();
+ FacesUtils.setRequestAttribute(fc, DB_CONTEXT_MAP, ctxMap);
+ }
+ ctxMap.put(conn.hashCode(), context);
+ // done
return conn;
}
@@ -487,14 +500,21 @@ public abstract class WebApplication
{
@SuppressWarnings("unchecked")
Map<DBDatabase, Connection> connMap = (Map<DBDatabase, Connection>) FacesUtils.getRequestAttribute(fc, CONNECTION_ATTRIBUTE);
+ @SuppressWarnings("unchecked")
+ Map<Integer, WebDBContext<? extends DBDatabase>> ctxMap = (Map<Integer, WebDBContext<? extends DBDatabase>>) FacesUtils.getRequestAttribute(fc, DB_CONTEXT_MAP);
if (connMap != null)
- { // Walk the connection map
+ { // Walk the connection map
for (Map.Entry<DBDatabase, Connection> e : connMap.entrySet())
{
- releaseConnection(e.getKey(), e.getValue(), commit);
+ Connection conn = e.getValue();
+ releaseConnection(e.getKey(), conn, commit);
+ // release connection
+ WebDBContext<? extends DBDatabase> ctx = ctxMap.get(conn.hashCode());
+ ctx.releaseConnection(commit);
}
// remove from request map
FacesUtils.setRequestAttribute(fc, CONNECTION_ATTRIBUTE, null);
+ FacesUtils.setRequestAttribute(fc, DB_CONTEXT_MAP, null);
}
}
diff --git a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/app/WebDBContext.java b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/app/WebDBContext.java
index e4c4394..da70293 100644
--- a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/app/WebDBContext.java
+++ b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/app/WebDBContext.java
@@ -1,12 +1,15 @@
package org.apache.empire.jsf2.app;
import java.sql.Connection;
+import java.sql.SQLException;
import javax.faces.context.FacesContext;
import org.apache.empire.db.DBDatabase;
import org.apache.empire.db.DBDatabaseDriver;
import org.apache.empire.db.context.DBContextBase;
+import org.apache.empire.db.exceptions.EmpireSQLException;
+import org.apache.empire.exceptions.InvalidArgumentException;
import org.apache.empire.exceptions.NotSupportedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -26,6 +29,9 @@ public class WebDBContext<DB extends DBDatabase> extends DBContextBase
private final WebApplication app;
private final DB database;
+ // Held for request only
+ private Connection conn;
+
public WebDBContext(WebApplication app, DB db)
{
this.app = app;
@@ -51,10 +57,42 @@ public class WebDBContext<DB extends DBDatabase> extends DBContextBase
* IMPORTANT: Do not hold the connection!
*/
@Override
- public Connection getConnection()
+ public synchronized Connection getConnection()
{
- FacesContext fc = FacesContext.getCurrentInstance();
- return this.app.getConnectionForRequest(fc, database);
+ if (conn==null)
+ { // get a new connection
+ FacesContext fc = FacesContext.getCurrentInstance();
+ conn = this.app.getConnectionForRequest(fc, this);
+ }
+ return conn;
+ }
+
+ @Override
+ public void commit()
+ {
+ if (conn!=null)
+ super.commit();
+ else
+ log.warn("No Connection to commmit");
+ }
+
+ @Override
+ public synchronized void rollback()
+ {
+ if (conn!=null)
+ super.commit();
+ else
+ log.warn("No Connection to rollbakc");
+ }
+
+ public synchronized void releaseConnection(boolean commitPerformed)
+ {
+ this.conn = null;
+ // commit or rollback?
+ if (commitPerformed)
+ discardAllHandlers();
+ else
+ rollbackAllHandlers();
}
/**
diff --git a/empire-db/src/main/java/org/apache/empire/db/context/DBContextBase.java b/empire-db/src/main/java/org/apache/empire/db/context/DBContextBase.java
index 59933ff..2490bc4 100644
--- a/empire-db/src/main/java/org/apache/empire/db/context/DBContextBase.java
+++ b/empire-db/src/main/java/org/apache/empire/db/context/DBContextBase.java
@@ -35,16 +35,12 @@ public abstract class DBContextBase implements DBContext
if (conn.getAutoCommit()==false)
conn.commit();
// discard rollbacks
- if (rollbackHandler!=null)
- for (DBRollbackHandler handler : rollbackHandler.values())
- handler.discard();
+ discardAllHandlers();
// Done
return;
} catch (SQLException sqle) {
// Commit failed!
throw new EmpireSQLException(getDriver(), sqle);
- } finally {
- rollbackHandler=null;
}
}
@@ -67,16 +63,12 @@ public abstract class DBContextBase implements DBContext
log.info("Database rollback issued!");
conn.rollback();
// rollback
- if (rollbackHandler!=null)
- for (DBRollbackHandler handler : rollbackHandler.values())
- handler.rollback();
+ rollbackAllHandlers();
// Done
return;
} catch (SQLException sqle) {
// Commit failed!
throw new EmpireSQLException(getDriver(), sqle);
- } finally {
- rollbackHandler=null;
}
}
@@ -110,6 +102,24 @@ public abstract class DBContextBase implements DBContext
public void discard()
{
/* don't close connection! */
+ discardAllHandlers();
+ }
+
+ protected void discardAllHandlers()
+ { // rollback
+ if (rollbackHandler==null)
+ return;
+ for (DBRollbackHandler handler : rollbackHandler.values())
+ handler.discard();
+ rollbackHandler=null;
+ }
+
+ protected void rollbackAllHandlers()
+ { // rollback
+ if (rollbackHandler==null)
+ return;
+ for (DBRollbackHandler handler : rollbackHandler.values())
+ handler.rollback();
rollbackHandler=null;
}