public interface ServerDataSourceImplementation
Bear in mind the following points when working with DataSources (whether custom or built-in) on the Smart GWT Server:
Spring-injected dataSources
, note that the
default scope for a Spring bean is "singleton". This means that a single instance of the bean
is cached by Spring and returned every time the framework code asks for that DataSource. This
pattern prevents the Smart GWT framework from making the above-mentioned guarantee that no
single instance will be used by multiple threads, and can lead to unpleasant concurrency bugs.
The solution is to mark your Spring beans with a scope of "prototype" (you could also use
"request", but Smart GWT caches DataSource instances per-HttpServletRequest anyway, so nothing
is gained by doing that). See the
Spring documentation for further information about bean scope.
transactional
and
non-transactional operations on the same DataSource instance in a single HTTP request can lead
to connection leaks if you are using the built-in Hibernate or JPA DataSource.
server.properties
attribute
datasource.cacheFailedLookups
is set, the server remembers the names of
DataSources it failed to look up, and does not attempt to look them up again (until the server
is restarted). This provides a negligible performance improvement in normal circumstances,
but can provide a more significant benefit in cases of questionable usage where DataSources or
field types are declared server-side, for use purely client-side. Note, if you set this flag, a
DataSource that you introduce in the middle of a running application will not be picked up if
the system has already cached a failed lookup of that DataSource.
server.properties
attribute
datasources.pool.enabled
is set, DataSource instances are automatically cached in
an in-memory pool. This caching is smart if server.properties
flag
datasources.enableUpToDateCheck
is set: if the underlying .ds.xml
file changes, cached instances are discarded and rebuilt. IMPORTANT: This facility is intended as a convenience for use on
development servers only. With enableUpToDateCheck:true
, your application may end
up using mixed versions of DataSources in a given HttpRequest, and this could lead to severe
consequences including data corruption. Consider, for example, the interaction between two
DataSources that have been redesigned and the server ends up using an older version of one
DataSource with a newer version of another; there are unlimited ways in which that kind of
scenario could prove disastrous. In short, setting enableUpToDateCheck:true
is
not safe for production environments - do not switch it on in production!
datasources.enableUpToDateCheckForComponentSchema
. This is the same as
enableUpToDateCheck
, but it controls whether we do the up-to-date checking in the
specific context of processing Component
Schema
. We make the distinction because, even if you want to use up-to-date checking for
your "ordinary" dataSources, most people will not have a requirement to support dynamically
changing Component Schema - it would only be necessary if you were building some kind of
visual tool like our Reify
low-code platform, or
possibly something based on the Dashboards and Tools
Framework
. If you leave this flag unset, it will use the setting of
datasources.enableUpToDateCheck
.ds.xml
file) is read the first time the
DataSource is requested; thereafter, we will only re-read the configuration file if its
last-changed timestamp changes. This scheme combines the performance benefits of caching with
the with the convenience of being able to change a .ds.xml
file and pick up the
changes without restarting the server.
RPCManager.getDataSource()
. If pooling is enabled, this is
the only way to obtain a DataSource instance with the guarantee that it will be returned to
the pool at the end of request processing.
DynamicDSGenerator
to provide DataSources to the framework dynamically:
DataSource.fromXML()
APIs to construct your
DataSources from an XML document or String of XML text
new DataSource()
, as this will introduce
thread-safety issues
DataSource.fromXML()
.
DynamicDSGenerator
, pooling is inappropriate because the returned
DataSource for a given name might be different each time the generator is called. For this
reason, pooling of dynamic DataSources is disabled by default. To enable pooling for
dynamically-generated DataSources, set the server.properties
flag datasources.poolDynamicDataSources
to true. Keep in mind,
that if pooling for dynamic DataSources is enabled, then DataSource definition must be the
same for the same DataSource ID. NOTE: Here, "dynamic DataSource" means a DataSource whose
name would cause the framework to invoke a DynamicDSGenerator, which doesn't necessarily mean
that the generator would actually create a dynamic DataSource. As the server-side
documentation for DynamicDSGenerator.getDataSource()
states, a generator can
simply return null to decline the opportunity to create a dynamic DataSource. Therefore, if the
proper operation of pooling is important to you, avoid patterns of
DynamicDSGenerator
usage that involve registering more generically than you need
to. In particular, avoid the addDynamicDSGenerator()
signature that does not
take a prefix or regex parameter - this will cause the pooling subsystem to regard all
DataSources as dynamic, and will effectively disable all DataSource pooling.