Main requirements for DB integration are
- decouple DB query execution from Event Router threads;
- present simple and convenient API reflecting data model semantics to be used
in Service Logic, e.g. getSubscriberInfo operation instead of executing
arbitrary SQL statements directly in SL.
- Performance.
Additional features:
- HA. Probably support provided by JBoss datasources is enough.
- Multiple queries on the same connection, transaction control.
Current Mobicents implementation of JDBC RA allows to execute a single query and
process the result set, then the connection returns to the pool. If there is a
need to execute multiple queries at once (where a query might depend on results
from the previous one), getting connection anew each time would be inefficient.
Transactions are also committed automatically after executing the request, while
there is sometimes the necessity to combine multiple queries into a single
transaction.
Now the alternative approaches for this problem.
1. Custom Database RA tailored for a particular data model
This satisfies main requirements: RA may freely manage its own thread pool as
well as implement a custom API based on Service Logic requirements and specifics
of the underlying data model. Moreover, as all interactions with database are
encapsulated inside this RA, it has complete freedom to manage connections and
transactions in any way needed.
Service (single SBB for brevity) communicates with the RA via a data
model-specific API
SL SBB <--- DMS API ---> DB RA <---> DATABASE
This is a simple, well known and tested approach. But what I don't like about it
is that you have to reimplement the RA every time to integrate a new data model
for another service either by reusing some stub like the current Mobicents JDBC
RA or by using some code generator and implementing the data model specifics on
top of that. Either way it is basically copy-paste programming which is the
weakest case of Reuse technology, because it is effective only in the short term
and causes an ever growing maintenance overhead in the long term.
2. Generic data model agnostic JDBC RA
In this case a generic JDBC RA (something similar to the current Mobicents JDBC
RA implementation) would be used. Such RA uses a separate thread pool to perform
SQL queries and passes back results as events, but does not know anything about
a specific data model. The function of presenting a convenient API related to
data model specifics would be delegated to a data integration child SBB.
SL DBB <--- DMS API ---> DI SBB <--- generic API ---> DB RA <---> DATABASE
The value of this approach is in the fact that such generic DB RA would be
reused with any service and any data model. Specifics of a given data model are
encapsulated in the Data Integration SBB, the RA is just a "dumb" gateway to a
database. Reusing the same identical component (DB RA) without any
customizations brings the advantages of Reuse like reduction of maintenance
effort, greater reliability, etc.
Alternative #2 looks superior from a purely theoretical point of view. However,
there is the problem of flexible transaction and connection management mentioned
above and some performance related considerations:
- if only a single query is allowed at once and a response to every single query
is routed as a new event, there is the obvious TPS (events) overhead in
scenarios where multiple queries are done, which is quite often the case (custom
RA would perform multiple interactions with DB and return a single response for
the logical data manipulation operation that was invoked).
- overhead of additional child SBB creation (we would need one or more Data
Integration SBBs per call per service). However, it should be possible to
encapsulate the data model specifics in some helper classes and just use that
lib in SL, avoiding adding a child.
Having in mind we are dealing with telco solutions, performance is key in
database integration as well - signalling and SL execution takes time, no
resources to waste here.
Thanks for attention, all and any comments very welcome.
--
Vilius Panevėžys
Elitnet
The support for such framework would require the RA to fire any event
type, but SLEE 1.1 allows this to be acceptable in the XML descriptor.
The actual custom event types would be deployed by the SBBs. Wrt for
the SBB service logic, I believe this would feel like a custom RA
Type, without the hassle to manage the build of a RA extension.
Community feedback?
-- Eduardo
2011/8/12 Vilius Panevėžys <vil...@elitnet.lt>:
Issue (including patch) at
http://code.google.com/p/mobicents/issues/detail?id=2825
A small summary, there is a new method in the
JdbcActivity#execute(JdbcTask task) , which allows execution of impl
of a particular task interface.
The task interface has a single method execute(SleeTransactionManager
txManager), which the RA will invoke to execute the task. The RA
exposes the SLEE Tx Manager through the method param.
The execution of the task must return a JdbcTaskResult object impl (if
null nothing more is done), which provides the RA the event object and
event type id to fired.
-- Eduardo
..............................................
http://emmartins.blogspot.com
http://redhat.com/solutions/telco
2011/8/30 Carl-Magnus Björkell <nrgiz...@gmail.com>:
We would've suggested an even simpler approach: provide connection to
JdbcTask.execute as parameter and close it (return to pool) right after task
execution is complete (patch line 344). This way the connection would be
returned to pool as soon as possible as well as avoiding possible deadlock as
Carl has explained.
Overall, we think Eduardo's proposed implementation addresses the discussed
needs well, making the JDBC RA suitable to be used as the universal DB access in
Mobicents, which has been lacking for a long time.
One additional feature that would be interesting to have is monitoring. I'm not
currently familiar if JBoss Datasources have anything to that end, but what we
have in mind is that as the JDBC RA is responsible for managing connections to a
DB it would be great to check the actual DB accessibility periodically and raise
a SLEE Alarm in case such a check fails. This way administrators could take
action possibly even before actual queries start to fail filling up logs with
exceptions.
--
Vilius Panevėžys
Elitnet
1) I'm not sure we should remove the getConnection methods from the RA
SBB Interface, this allows SBBs, which have no high performance needs,
to do sync JDBC interactions. In summary it allows a model where the
RA is used to simply expose the managed Java datasource, independent
of how this is actually done in the underlying Java EE AS. Surely this
allows bad SBBs from exhausting the Connection pool so perhaps the RA
should have a config property indicating if these methods are "on" or
"off", and in restricted environments, where the SLEE admin does not
truly controls SBBs, it is configured as "off" and these methods
throws a SecurityException if invoked.
2) About exposing a task context, that provides also means to get a
connection, which is automatically closed once the task execution
completes, I think that is a must if we have a restricted setup as
defined in 1). Now does it make any sense to allow more than one
connection during the task execution?
3) With respect to Java transactions, I first thought of not exposing
the tx manager, instead the task would signal the RA that execution
would be under a tx, and would have a way to signal that the tx should
rollback, similar to the way SBBs indicate that through the sbb
context. My concern was then how commit failure or rollback feedback
would be provided to the SBB, we could again mimic what happens in the
sbb and provide an additional failure event (besides the execution
exception one) indicating such info, but it was not clear to me how
that feedback can be of any good, mainly because it would be the RA
giving the feedback, not the task, so I ended up deciding for full tx
manager control by the task, that is, it may build any event if it
fails to commit or decides to rollback during the logic execution. The
RA simply ensures that any open tx is closed after the task execution
(with a friendly commit() invocation). Anything to comment about this?
4) About removing the other execute methods in the JdbcActivity due to
Connection pool exhaustion again, I'm fine with it, but I don't like
the fact an app needs to have the burden of developing custom events
or even have to implement complete JdbcTasks for simple operations.
Simplicity in the RA usage is a must, so maybe we could have a
"simple" child package, including an abstract class of task and an
pre-installed event type, the task execution would return instead a
plain data Object as result, which would then be included in the
event...
-- Eduardo
..............................................
http://emmartins.blogspot.com
http://redhat.com/solutions/telco
2011/9/2 Carl-Magnus Björkell <nrgiz...@gmail.com>:
2011/9/2 Vilius Panevėžys <vil...@elitnet.lt>:
> Hi,
> sorry for the delay from our side. However, it turns out to be a good thing
> as Carl has already outlined most of the concerns we have been thinking
> about as well. :)
>
> We would've suggested an even simpler approach: provide connection to
> JdbcTask.execute as parameter and close it (return to pool) right after task
> execution is complete (patch line 344). This way the connection would be
> returned to pool as soon as possible as well as avoiding possible deadlock
> as Carl has explained.
This is not straightforward as it seems, my first idea was to do that,
but connections may need user and password, so would need to pollute
the task impl with method(s) for the RA to retrieve these params. I
think the alternative of allowing the task to get it from an task
context is "cleaner", but the RA may have to deal with the complexity
of a bad task trying to get multiple connections... Carl and anyone
else in the community (feel free to participate in the discussion!)
what would be your preference?
> Overall, we think Eduardo's proposed implementation addresses the discussed
> needs well, making the JDBC RA suitable to be used as the universal DB
> access in Mobicents, which has been lacking for a long time.
>
> One additional feature that would be interesting to have is monitoring. I'm
> not currently familiar if JBoss Datasources have anything to that end, but
> what we have in mind is that as the JDBC RA is responsible for managing
> connections to a DB it would be great to check the actual DB accessibility
> periodically and raise a SLEE Alarm in case such a check fails. This way
> administrators could take action possibly even before actual queries start
> to fail filling up logs with exceptions.
Sounds good to me, but for a later revision once we settle for the
final 1.0 RA Type and impl. Multiple datasource load balancing could
be interesting too...
Respecting Eduardo's concern with making the implementation as universal as
possible, I agree that if some additional parameters are needed in the JdbcTask
(credentials or anything else that did not cross my mind yet) the cleanest way
to hand them over is to use a single holder object (task context) instead of
getting each param using a separate RA's getter. Talking about the credentials
in particular, I don't see that as a really attractive feature, but more
opinions might be useful.
Moreover, giving a context holder object to the task does not conflict with
assigning a particular connection to a particular task. The connection might
event be part of the context.
And yes, I would definitely vote for adding the multiple datasource load
balancing and seamless fail-over to the wish list. :)
--
Vilius Panevėžys
Elitnet
http://code.google.com/p/mobicents/issues/detail?id=2825
Note that docs won't be updated till we settle on the Java code.
-- Eduardo
..............................................
http://emmartins.blogspot.com
http://redhat.com/solutions/telco
2011/9/2 Vilius Panevėžys <vil...@elitnet.lt>:
Right now I don't have any immediate propositions (apart from additional
interesting features mentioned in this thread), we'll have to build some real
world use cases off this API to find new ways to make it better. :)
And with regard to documenting, I think special attention will be needed to
explain how easy it is to do simple use cases (using the task.simple package) to
not make it look like JDBC RA lost functionality and advanced use cases like
transaction control.
Thanks a lot to Eduardo for great responsiveness and great code and Carl for
sharing your thoughts.
--
Vilius Panevėžys
Elitnet
-- Eduardo
..............................................
http://emmartins.blogspot.com
http://redhat.com/solutions/telco
2011/9/5 Vilius Panevėžys <vil...@elitnet.lt>: