diff --git a/jetty-documentation/src/main/asciidoc/distribution-guide/sessions/session-configuration-jdbc.adoc b/jetty-documentation/src/main/asciidoc/distribution-guide/sessions/session-configuration-jdbc.adoc
index a93320d34112..2badd001afc2 100644
--- a/jetty-documentation/src/main/asciidoc/distribution-guide/sessions/session-configuration-jdbc.adoc
+++ b/jetty-documentation/src/main/asciidoc/distribution-guide/sessions/session-configuration-jdbc.adoc
@@ -85,6 +85,16 @@ db-connection-type=datasource
#jetty.session.jdbc.schema.maxIntervalColumn=maxInterval
#jetty.session.jdbc.schema.mapColumn=map
#jetty.session.jdbc.schema.table=JettySessions
+# Optional name of the schema used to identify where the session table is defined in the database:
+# "" - empty string, no schema name
+# "INFERRED" - special string meaning infer from the current db connection
+# name - a string defined by the user
+#jetty.session.jdbc.schema.schemaName
+# Optional name of the catalog used to identify where the session table is defined in the database:
+# "" - empty string, no catalog name
+# "INFERRED" - special string meaning infer from the current db connection
+# name - a string defined by the user
+#jetty.session.jdbc.schema.catalogName
----
jetty.session.gracePeriod.seconds::
@@ -111,4 +121,14 @@ jetty.session.jdbc.driverUrl::
Url of the database which includes the driver type, host name and port, service name and any specific attributes unique to the database, such as a username.
As an example, here is a mysql connection with the username appended: `jdbc:mysql://127.0.0.1:3306/sessions?user=sessionsadmin`.
-The `jetty.sessionTableSchema` values represent the names for the columns in the JDBC database and can be changed to suit your environment.
+The `jetty.session.jdbc.schema.*` values represent the names of the table and columns in the JDBC database used to store sessions and can be changed to suit your environment.
+
+There are also two special, optional properties: `jetty.session.jdbc.schema.schemaName` and `jetty.session.jdbc.schema.catalogName`.
+The exact meaning of these two properties is dependent on your database vendor, but can broadly be described as further scoping for the session table name.
+See https://en.wikipedia.org/wiki/Database_schema and https://en.wikipedia.org/wiki/Database_catalog.
+These extra scoping names can come into play at startup time when jetty determines if the session table already exists, or otherwise creates it on-the-fly.
+If you have employed either of these concepts when you pre-created the session table, or you want to ensure that jetty uses them when it auto-creates the session table, then you have two options: either set them explicitly, or let jetty infer them from a database connection (obtained using either a Datasource or Driver according to the `db-connection-type` you have configured).
+To set them explicitly, uncomment and supply appropriate values for the `jetty.session.jdbc.schema.schemaName` and/or `jetty.session.jdbc.schema.catalogName` properties.
+To allow jetty to infer them from a database connection, use the special string `INFERRED` instead.
+If you leave them blank or commented out, then the sessions table will not be scoped by schema or catalog name.
+
diff --git a/jetty-server/src/main/config/etc/sessions/jdbc/session-store.xml b/jetty-server/src/main/config/etc/sessions/jdbc/session-store.xml
index 9b66771b9a8a..6544aa72d33f 100644
--- a/jetty-server/src/main/config/etc/sessions/jdbc/session-store.xml
+++ b/jetty-server/src/main/config/etc/sessions/jdbc/session-store.xml
@@ -54,6 +54,12 @@
+
+
+
+
+
+
diff --git a/jetty-server/src/main/config/modules/session-store-jdbc.mod b/jetty-server/src/main/config/modules/session-store-jdbc.mod
index e97457d07814..b367e3643090 100644
--- a/jetty-server/src/main/config/modules/session-store-jdbc.mod
+++ b/jetty-server/src/main/config/modules/session-store-jdbc.mod
@@ -55,3 +55,14 @@ db-connection-type=datasource
#jetty.session.jdbc.schema.maxIntervalColumn=maxInterval
#jetty.session.jdbc.schema.mapColumn=map
#jetty.session.jdbc.schema.table=JettySessions
+# Optional name of the schema used to identify where the session table is defined in the database:
+# "" - empty string, no schema name
+# "INFERRED" - special string meaning infer from the current db connection
+# name - a string defined by the user
+#jetty.session.jdbc.schema.schemaName
+# Optional name of the catalog used to identify where the session table is defined in the database:
+# "" - empty string, no catalog name
+# "INFERRED" - special string meaning infer from the current db connection
+# name - a string defined by the user
+#jetty.session.jdbc.schema.catalogName
+
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionDataStore.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionDataStore.java
index 32b6f1d2b57f..279f65fe6c24 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionDataStore.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionDataStore.java
@@ -66,9 +66,11 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
public static class SessionTableSchema
{
public static final int MAX_INTERVAL_NOT_SET = -999;
+ public static final String INFERRED = "INFERRED";
protected DatabaseAdaptor _dbAdaptor;
protected String _schemaName = null;
+ protected String _catalogName = null;
protected String _tableName = "JettySessions";
protected String _idColumn = "sessionId";
protected String _contextPathColumn = "contextPath";
@@ -87,7 +89,20 @@ protected void setDatabaseAdaptor(DatabaseAdaptor dbadaptor)
{
_dbAdaptor = dbadaptor;
}
+
+ public void setCatalogName(String catalogName)
+ {
+ if (catalogName != null && StringUtil.isBlank(catalogName))
+ _catalogName = null;
+ else
+ _catalogName = catalogName;
+ }
+ public String getCatalogName()
+ {
+ return _catalogName;
+ }
+
public String getSchemaName()
{
return _schemaName;
@@ -95,8 +110,10 @@ public String getSchemaName()
public void setSchemaName(String schemaName)
{
- checkNotNull(schemaName);
- _schemaName = schemaName;
+ if (schemaName != null && StringUtil.isBlank(schemaName))
+ _schemaName = null;
+ else
+ _schemaName = schemaName;
}
public String getTableName()
@@ -484,28 +501,48 @@ public void prepareTables()
//make the session table if necessary
String tableName = _dbAdaptor.convertIdentifier(getTableName());
+
String schemaName = _dbAdaptor.convertIdentifier(getSchemaName());
- try (ResultSet result = metaData.getTables(null, schemaName, tableName, null))
+ if (INFERRED.equalsIgnoreCase(schemaName))
+ {
+ //use the value from the connection -
+ //NOTE that this value will also now be prepended to ALL
+ //table names in queries/updates.
+ schemaName = connection.getSchema();
+ setSchemaName(schemaName);
+ }
+ String catalogName = _dbAdaptor.convertIdentifier(getCatalogName());
+ if (INFERRED.equalsIgnoreCase(catalogName))
+ {
+ //use the value from the connection
+ catalogName = connection.getCatalog();
+ setCatalogName(catalogName);
+ }
+
+ try (ResultSet result = metaData.getTables(catalogName, schemaName, tableName, null))
{
if (!result.next())
{
+ if (LOG.isDebugEnabled())
+ LOG.debug("Creating table {} schema={} catalog={}", tableName, schemaName, catalogName);
//table does not exist, so create it
statement.executeUpdate(getCreateStatementAsString());
}
else
{
+ if (LOG.isDebugEnabled())
+ LOG.debug("Not creating table {} schema={} catalog={}", tableName, schemaName, catalogName);
//session table exists, check it has maxinterval column
ResultSet colResult = null;
try
{
- colResult = metaData.getColumns(null, schemaName, tableName,
+ colResult = metaData.getColumns(catalogName, schemaName, tableName,
_dbAdaptor.convertIdentifier(getMaxIntervalColumn()));
}
catch (SQLException sqlEx)
{
- LOG.warn("Problem checking if " + getTableName() +
- " table contains " + getMaxIntervalColumn() + " column. Ensure table contains column definition: \"" +
- getMaxIntervalColumn() + " long not null default -999\"");
+ LOG.warn("Problem checking if {} table contains {} column. Ensure table contains column with definition: long not null default -999",
+ getTableName(), getMaxIntervalColumn());
throw sqlEx;
}
try
@@ -519,9 +556,7 @@ public void prepareTables()
}
catch (SQLException sqlEx)
{
- LOG.warn("Problem adding " + getMaxIntervalColumn() +
- " column. Ensure table contains column definition: \"" + getMaxIntervalColumn() +
- " long not null default -999\"");
+ LOG.warn("Problem adding {} column. Ensure table contains column definition: long not null default -999", getMaxIntervalColumn());
throw sqlEx;
}
}
@@ -538,7 +573,7 @@ public void prepareTables()
boolean index1Exists = false;
boolean index2Exists = false;
- try (ResultSet result = metaData.getIndexInfo(null, schemaName, tableName, false, true))
+ try (ResultSet result = metaData.getIndexInfo(catalogName, schemaName, tableName, false, true))
{
while (result.next())
{
@@ -559,8 +594,8 @@ else if (index2.equalsIgnoreCase(idxName))
@Override
public String toString()
{
- return String.format("%s[%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s]", super.toString(),
- _schemaName, _tableName, _idColumn, _contextPathColumn, _virtualHostColumn, _cookieTimeColumn, _createTimeColumn,
+ return String.format("%s[%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s]", super.toString(),
+ _catalogName, _schemaName, _tableName, _idColumn, _contextPathColumn, _virtualHostColumn, _cookieTimeColumn, _createTimeColumn,
_expiryTimeColumn, _accessTimeColumn, _lastAccessTimeColumn, _lastNodeColumn, _lastSavedTimeColumn, _maxIntervalColumn);
}
}