So our application is almost in production, and we realized that the proof-of-concept RESTful interface I created (using a jOOQ configuration wrapping a JDBC connection) had never been changed, so all requests were using the same connection! I'm now reviewing another teammate's changes and I wanted to review the jOOQ documentation on this, as this is a little beyond my expertise. So I looked for the documentation that used to exist, but the version 3.4 manual doesn't seem to have anything to say on the subject!
Where can I read up on how to create a single jOOQ configuration that I pass around that uses a data source or some other connection factory (that I can e.g. put a connection pool behind)? Where's the new documentation for that? Thanks.
Thanks for the reply, Lukas. So here's where it gets interesting, taking us back to the whole "with jOOQ you don't need an ORM" issue, which I don't think is as clear-cut as some comments might make it appear.
Let's say I have a Car class (identified by some vehicle identification number VIN) and a Wheel class, and I want to store a car in a database along with its four wheels. If two people try to store the Car in the database at the same time, I don't care who wins, but I want the whole operation to be atomic, and I want it to replace whatever Car is already in the database (if any) with the same VIN.
I also have a CarManager class (which has an implementation JOOQCarManager) along with a WheelManager class (with implementation JOOQWheelManager).
I set up a dbcp2 PoolingDataSource (for example) and then create a jOOQ configuration using:
final org.jooq.Configuration jooqConfiguration = new DefaultConfiguration()
.set(dataSource).set(SQLDialect.POSTGRES).set(new Settings().withExecuteLogging(true));
Somehow that jooqConfiguration instance gets put in some dependency injection container; we don't care how, we only care that the managers have access to it.
So inside JOOQCarManager.storeCar(Car car) I create a DSLContext:
DSLContext dslContext=DSL.using(getConfiguration())
Question 1: So what do I do now? Do I just start using the DSLContext and it will get a connection as needed? Or do I do this?
Connection connection = dslContext.configuration().connectionProvider().acquire();
DSLContext dslContext=DSL.using(getConfiguration())
Question 2: How do I start a transaction? The code I'm reviewing (a mix of several people's code) does this:
DSLContext dslTransaction = DSL.using(connection);
dslTransaction.execute("SET CONSTRAINTS ALL DEFERRED");
... //and then goes on to delete the Car if it exists
final int deleteCount = dslTransaction.delete(CAR).where(CAR.VIN.equal(vin).execute();
final CarRecord carRecord = dslTransaction.newRecord(CAR);
... //etc. to store the Car info
Question 3: So what happens when we want to store the wheels? Does JOOQCarManager call its instance of JOOQWheelManager four times?
But how does JOOQWheelManager make sure that it's part of the same transaction?
If JOOQWheelManager creates a new DSLContext from the jOOQ Configuration from the DI container, won't that start a new transaction?
Do we have to pass the current DSLContext to the WheelManager? Or do we pass the JDBC Connection to the WheelManager, which will use it to form a DSLContext that uses the same connection?
I apologize if some of these questions have obvious answers. In fact I hope they do. I am not a relational database expert, but unfortunately I'm the one who gets to research all this stuff for my client's application.
I would think that the above scenario is very common and in fact "standard" to some extent when storing an instance tree in a database. I'm hoping there is a straightforward and "standard" solution.
Thanks so much, Lukas. I'm immediately going to be hitting the books.
I want to mention that we are not using Spring. We are using an embedded Jetty instance with a RESTEasy REST interface on one side and a Wicket web interface on the other. As you know I'm a bit behind on the latest JavaEE database stuff, so if Servlet 3 and Jetty help us out, great. (I will know more after reading this weekend.) Otherwise, the only thing "taking care of things for us" will be jOOQ and JDBC, so I'm not sure if @Transactional et. al. is going to help us out.
[name].transaction(() -> { work to be done }
Hi guys,
The problems with JDBC transactions is that you either have to use raw
connections to perform operations like commit and rollback, or you
have to use some heavy heavy stuff like EJB or Spring.
When using jOOQ, there is also third option, introduced by Lukas in
version 3.4.x, but it is... well, it is useless in anything other than
a script (sorry for being straight), because one have to pass a
context/configuration/whatever_you_call_it object everywhere, working
essentially as a transaction. So in anything other than a simple
script, we are left alone with "go use Spring or EJB".
As Roger pointed, one could also use Sprint TX module of Spring
framework. I was almost convinced to do it, since I have just created
a simple microservice in Java with jOOQ and I need transactions.
Question: did you see the Spring source code? After 30 minutes of this
painful experience I decided to never, ever think about using Spring
anywhere anytime.
I remember having a discussion with Lukas, trying to stop him
introducing transactions into jOOQ API. My proposition was to create a
"jOOT", an ultra lightweight transaction manager which could be used
anywhere we want tx management with JDBC (plain JDBC, jOOQ, QueryDSL,
standalone Hibernate, Toplink or other home-grown lib).
I have even created https://github.com/witoldsz/joot-playground
Months passed and I am here, with jOOQ/JDBC microservice and missing
transaction management, so I have decided to implement the concept
described above myself. The problem is I have to figure out the name,
I cannot use jOOT of course. My first shot is "ULTM" - The Ultra
Lightweight Transaction Management for JDBC. The beta version, with
limited capabilities (for start: no nested transactions and some other
restrictions) is like almost ready. It took me few hours so far.
The very basic concept is like this: "you give me your DataSource and
I will give back TxManager and another, managed DataSource and you
will use that DataSource instead of the original one". And all that
with few dozen lines of code (I hope) with no other, external
dependencies.
Hi Lukas,
The difference is crucial. The configuration object is created while creating transaction, in jOOQ one have to pass it around manually. Let's say I am opening tx on message arrival, then router routes to some handler, it routes further somewhere (like DAO or something). Typical case for even tiny app. Passing config object is not an option.
My solution allows one to configure DSLContext at the boot stage of an app (like in EJB or Spring) and then just use it. And this is how I use it in my microservice.
Regards,
Witold Szczerba
--
Hi,
I am not sure I am following.
You mentioned Spring transactions are working in two modes: implicit
by annotations and explicit using tx manager API. That is true. It is
the same in EJB, where you can use UserTransaction or declarative
transactions. But none of them are forcing users to pass some kind of
context object around.
This is not an option anywhere but scripts.
Imagine adding jooq.Configuration (or something like it) to every
method signature, including business interfaces?
It is not like the current jOOQ transaction management is equivalent
of Spring or EJB "manual" mode. The ULTM or jOOT are and since JDBC is
a blocking API by design, all of them are working essentially as you
described, using ThreadLocal.
BTW: the way jOOQ transactions works now, with nesting support, are
much more advanced than what I have done in ULTM. I wish I haven't had
to create ULTM in the first place :)
Yes, Lukas, this is all helping immensely. I'm away from my computer, but ULTM sounds like it's what we could use. I was hoping not to bring in even a fingernail on the monster that is Spring. G
Andrey.
Sent from my Nexus 4
On Nov 17, 2014 11:37 AM, "Lukas Eder" <lukas...@gmail.com> wrote:
>
> Yes, I understand that part of the difference - and I remember your criticism. Essentially, jOOQ currently expects you to pass the transaction reference (as contained in a derived Configuration) around, whereas ULTM probably keeps it somewhere in a ThreadLocal. In jOOQ, the "ThreadLocal solution" might emerge in a future version as well, in parallel to the existing explicit version (https://github.com/jOOQ/jOOQ/issues/2732). I can't promise any ETA, as this might introduce significant changes to all of jOOQ's internals.
>
> But having both models in parallel isn't so uncommon. In Spring, for instance, you can also choose to use "implicit" transactions via @Transactional annotations, or "explicit" ones via a transaction manager that you have to keep around. In the end, there are these two models. I don't see a clear advantage of one over the other, apart from personal taste. But I agree that jOOQ currently doesn't offer the "implicit" model.
>
Implicit is always better than implicit. Personally I prefer the current tx jOOQ api over any other like spring...
It is very flexible and allow implement own implicit tx management without much of problems.
Implicit tx management is not suitable for all cases. In my opinion any implicit transaction management should be out of scope of jOOQ (different library is a good place for it...)
> Having said so, I believe that it is a great idea to publish your transaction framework! I suggest you put a couple of well-documented examples in a README.md file of your GitHub repository. You don't necessarily need a Google Group, I think. For starters, communication via GitHub issues might be sufficient.
>
> If you're interested in publishing a guest post on the jOOQ blog, let me know. We're syndicated with DZone, JCG, JAXenter.com, Tech.Pro, and we're also talking to voxxed.com (a new collaboration between Devoxx and Parleys). This might help you kick-start your transaction API.
>
> Cheers,
> Lukas
>
My two cents.
Greetings.
Andrey
Yes, Lukas, this is all helping immensely. I'm away from my computer, but ULTM sounds like it's what we could use. I was hoping not to bring in even a fingernail on the monster that is Spring. G
Andrey.
Sent from my Nexus 4
On Nov 17, 2014 11:37 AM, "Lukas Eder" <lukas...@gmail.com> wrote:
>
> Yes, I understand that part of the difference - and I remember your criticism. Essentially, jOOQ currently expects you to pass the transaction reference (as contained in a derived Configuration) around, whereas ULTM probably keeps it somewhere in a ThreadLocal. In jOOQ, the "ThreadLocal solution" might emerge in a future version as well, in parallel to the existing explicit version (https://github.com/jOOQ/jOOQ/issues/2732). I can't promise any ETA, as this might introduce significant changes to all of jOOQ's internals.
>
> But having both models in parallel isn't so uncommon. In Spring, for instance, you can also choose to use "implicit" transactions via @Transactional annotations, or "explicit" ones via a transaction manager that you have to keep around. In the end, there are these two models. I don't see a clear advantage of one over the other, apart from personal taste. But I agree that jOOQ currently doesn't offer the "implicit" model.
>Implicit is always better than implicit. Personally I prefer the current tx jOOQ api over any other like spring...
It is very flexible and allow implement own implicit tx management without much of problems.Implicit tx management is not suitable for all cases. In my opinion any implicit transaction management should be out of scope of jOOQ (different library is a good place for it...)
| (defn atomic-apply | |
| "Execute a function in one transaction | |
| or subtransaction." | |
| [^Context ctx func & args] | |
| (let [^Configuration conf (.derive (proto/get-configuration ctx)) | |
| ^TransactionContext txctx (transaction-context conf) | |
| ^TransactionProvider provider (.transactionProvider conf)] | |
| (doto conf | |
| (.data "suricatta.rollback" false) | |
| (.data "suricatta.transaction" true)) | |
| (try | |
| (.begin provider txctx) | |
| (let [result (apply func (types/->context conf) args) | |
| rollback? (.data conf "suricatta.rollback")] | |
| (if rollback? | |
| (.rollback provider txctx) | |
| (.commit provider txctx)) | |
| result) | |
| (catch Exception cause | |
| (.rollback provider (.cause txctx cause)) | |
| (if (instance? RuntimeException cause) | |
| (throw cause) | |
| (throw (DataAccessException. "Rollback caused" cause))))))) |
Hi Andrey,2014-11-17 15:51 GMT+01:00 Andrey Antukh <ni...@niwi.be>:Andrey.
Sent from my Nexus 4
On Nov 17, 2014 11:37 AM, "Lukas Eder" <lukas...@gmail.com> wrote:
>
> Yes, I understand that part of the difference - and I remember your criticism. Essentially, jOOQ currently expects you to pass the transaction reference (as contained in a derived Configuration) around, whereas ULTM probably keeps it somewhere in a ThreadLocal. In jOOQ, the "ThreadLocal solution" might emerge in a future version as well, in parallel to the existing explicit version (https://github.com/jOOQ/jOOQ/issues/2732). I can't promise any ETA, as this might introduce significant changes to all of jOOQ's internals.
>
> But having both models in parallel isn't so uncommon. In Spring, for instance, you can also choose to use "implicit" transactions via @Transactional annotations, or "explicit" ones via a transaction manager that you have to keep around. In the end, there are these two models. I don't see a clear advantage of one over the other, apart from personal taste. But I agree that jOOQ currently doesn't offer the "implicit" model.
>Implicit is always better than implicit. Personally I prefer the current tx jOOQ api over any other like spring...
It is very flexible and allow implement own implicit tx management without much of problems.Implicit tx management is not suitable for all cases. In my opinion any implicit transaction management should be out of scope of jOOQ (different library is a good place for it...)
For the group: Andrey has implemented Suricatta (http://niwibe.github.io/suricatta). A SQL API built on top of jOOQ for Clojure.
Andrey: I haven't had a look at the implementation details of your TransactionProvider yet. If I'm not mistaken, the sources are these ones here, right?
--
You received this message because you are subscribed to the Google Groups "jOOQ User Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jooq-user+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
OK, I get it now. It is just that for me it was not acceptable to pass context object around from one layer to another.
Let me show you, with code example, to demonstrate, what was the problem with jOOQ transactions in my case.This post is targeted to anyone interested in this subject, but Lukas, you can just skip it as there is nothing new for you here :)The piece of code below is a generic message handler, part of a shared common lib inside my project which is made of dozens of microservices with 3 of them being in JVM. The handler is invoked when messages arrive. Such a code snippets I had in many other projects, but this one is the first when I do not use any application server (and I like it that way), so I had to take care of transactions by myself instead of making it done automagically by EJB.Part of this is a RabbitMQ SPI, but it would be almost the same in any other scenario like simple HTTP handler, servlet, JAX-RS or the like.// full version there://MQueue mQueue = new MQueue(channel, ...);[...]// few lines later@Overridepublic void handleDelivery(...) {try {txManager.txChecked(() -> mQueue.onMessage(message));// look how it would be with jOOQ:// but this tiny message handling project knows nothing about jOOQ// jooq.transaction(ctx -> mQueue.onMessage(message, ctx));
if (!p.autoAck) channel.basicAck(...);} catch (Exception ex) {if (!p.autoAck) channel.basicNack(...);}}There are other ways to make it work without storing transaction context in ThreadLocal, in the future - who knows, maybe I would add other ways of fetching tx context, but I guess they would have to depend on environment, like Guice's scopes.
public void method() {try {scope.init("method()");// User method body here}finally {scope.close();}}
Of course I could extend the mQueue#onMessage method, so it would use some proprietary transaction/configuration object from jOOQ, but this is just a generic message handler, it knows nothing about who will actually consume that message, maybe the consumer does not know anything about jOOQ at all and do not have it on it's classpath.
Another problem distributing by reference passing some kind of context is that the MQueue class, which is responsible for routing the exact message to the correct object, would have pass that context yet again (and then maybe yet again), so now my tiny and generic message handling library is not only packed with jOOQ API (which is actually not included there at all) but it also forces all the target consumers to declare dependency on jOOQ context on each handler even if they do not use it at all.Now, the transaction manager as I asked from the very beginning would work in a different way. What I did with ULTM was actually a carbon-copy of what I used to in big and fat environments like EJB. The only exception is that it is like gazillion times simpler, the only thing that is left is the idea of transparent transaction management. So, I do not care what kind of JDBC library my consumers will use. All I want is to make my library wrap message destination handler within generic transaction (which depends on raw JDBC DataSource) and do a commit/rollback at the end of processing. And if there was no JDBC calls at all - then nothing is happening.
And last, but not least, the "transparent" JDBC transaction management is simple to use, yet universal. It does not add complexity to any JDBC library. It allows me to use jOOQ, plain JDBC, Hibernate
or whatever together or separably and the outer layer of my application (or microservice) does not care. I heard there are people using jOOQ with JPA/Hibernate.
They would benefit as well, because the transaction would span them all.Having said all that, I can see the use case of the transaction management built into jOOQ. I do not like it, but at least I can see others who do and it works for them.
Ah, now I can see you wrote you use DI and I asked that question. Sorry about that.
Regards,
Witold Szczerba
--
You received this message because you are subscribed to the Google Groups "jOOQ User Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jooq-user+unsubscribe@googlegroups.com.
There is no mailing list for ULTM, but fell free to ask question on
issue tracker, because I am not sure if people here are interested :)
Yes, I realize this documentation is really old, but Lukas, the link there for 3.5 is broken.
...
So now that this SQL statement is finished and executed, jOOQ will "close" the connection, which normally would return it to the pool. Does TxManager step in and keep the connection from going back into the pool?Yes, it does. Connection does not go back to pool yet.9. So now let's start storing the car: CarRecord carRecord = dslTransaction.newRecord(CAR); ... carRecord.store(); Again, where does jOOQ get its connection? Does the managed data source ensure that it gets the same connection as before? After the transaction is over, does the manage data source simply pass the connection requests (that are not part of any transaction) on to the underlying data source? If this is how it all works, then I suppose it's starting to make sense.As I said in previous posts, jOOQ will get the same connection each time within TxManager transaction. It won't close, commit, rollback or give it back to the pool until TxManager say so.
On 12/9/2014 7:52 AM, Witold Szczerba wrote:
...So now that this SQL statement is finished and executed, jOOQ will "close" the connection, which normally would return it to the pool. Does TxManager step in and keep the connection from going back into the pool?Yes, it does. Connection does not go back to pool yet.9. So now let's start storing the car: CarRecord carRecord = dslTransaction.newRecord(CAR); ... carRecord.store(); Again, where does jOOQ get its connection? Does the managed data source ensure that it gets the same connection as before? After the transaction is over, does the manage data source simply pass the connection requests (that are not part of any transaction) on to the underlying data source? If this is how it all works, then I suppose it's starting to make sense.As I said in previous posts, jOOQ will get the same connection each time within TxManager transaction. It won't close, commit, rollback or give it back to the pool until TxManager say so.
OK, Witold, that makes sense and I like it. But just to clear up in my mind how this all works, I wonder about the default jOOQ behavior if I simply have a jOOQ Configuration wrapping a data source (with no Spring and no pooling and no anything else).
Lukas, if I do not use ULTM, and if I manually turn off autocommit on a connection and then issue several jOOQ SQL commands, will jOOQ (via the DataSourceConnectionProvider) request a different connection for each command?
(I read that jOOQ will close the connection after execution of each command.)
If so, then it would seem that all of the jOOQ commands are using separate connections, because in this scenario I have no connection pool and I don't have ULTM installed.
To simplify my question: with a DSLContext created from a jOOQ configuration backed by a data source, if I manage transactions manually on a connection,
what is stopping jOOQ from creating new connections for each command using the default DataSourceConnectionProvider?
(I am beginning to think that the answer is, "this won't work, because jOOQ will indeed request a new connection for each command.
I suspect it only works in our application because the developer is passing around a JDBC connection instance during a transaction, and forming a DSLContext via DSL.using(connection) from the transaction connection rather than DSL.using(jooqConfiguration).)
Just checking, have you already used a debugger to step through all the jOOQ / ULTM code, etc?
Lukas, if I do not use ULTM, and if I manually turn off autocommit on a connection and then issue several jOOQ SQL commands, will jOOQ (via the DataSourceConnectionProvider) request a different connection for each command?
Where would you turn off autocommit manually, if you use a DataSource? Did you implement your own DataSource?
(I am beginning to think that the answer is, "this won't work, because jOOQ will indeed request a new connection for each command.
No. jOOQ will request ANY Connection for each command. jOOQ doesn't care how YOU produce that Connection. That's your business.
On 12/10/2014 2:12 PM, Lukas Eder wrote:
Just checking, have you already used a debugger to step through all the jOOQ / ULTM code, etc?
Lukas, I confess I haven't. Things have been crazy with several projects flying around, and today I'm a little extra lazy because it's my birthday.
Lukas, if I do not use ULTM, and if I manually turn off autocommit on a connection and then issue several jOOQ SQL commands, will jOOQ (via the DataSourceConnectionProvider) request a different connection for each command?
Where would you turn off autocommit manually, if you use a DataSource? Did you implement your own DataSource?
I'm reviewing code of a colleague, and it looks like this:
connection = dslContext.configuration().connectionProvider().acquire();
connection.setAutoCommit(false);
Thereafter the code uses jOOQ to do stuff, but the code gets a DSLContext by:
DSL.using(connection)
So my question was just to make sure I understood things. If the code instead used DSL.using(jooqConfiguration), then it would break the entire transaction, because jOOQ would request a new connection which wouldn't be the one we're working on above.
try (Connection connection = datasource.getConnection()) {connection.setAutoCommit(false);
try {
DSL.using(connection) ... // <<-- The only actually interesting code is here
connection.commit();}
catch (Exception e) {
try {
connection.rollback();}
catch (Exception e2) {
e.addSuppressed(e2);
}
throw e;
}
}
(I am beginning to think that the answer is, "this won't work, because jOOQ will indeed request a new connection for each command.
No. jOOQ will request ANY Connection for each command. jOOQ doesn't care how YOU produce that Connection. That's your business.
But I don't produce the connection. The ConnectionProvider produces the connection, right? And in my example earlier, I indicated "I simply have a jOOQ Configuration wrapping a data source (with no Spring and no pooling and no anything else)", in which case jOOQ uses a DataSourceConnectionProvider, correct? So jOOQ will request a connection for each command, and that will wind up being a new connection from the data source. That's how I understand it anyway.
...
So, I know you said that your project is in a bit of a hurry and that you're lazy, etc :-)
...
Well, I still don't know how you created that DataSource and I thus don't know why you're assuming that it is creating a new Connection every time for jOOQ. It might be. But that's the DataSource's responsibility, not jOOQ's. So again, how *did* you implement that DataSource? (And why don't you use some connection pool?)
On 12/11/2014 7:15 AM, Lukas Eder wrote:
...
So, I know you said that your project is in a bit of a hurry and that you're lazy, etc :-)
Yes, the project is in too much of a hurry and it's understaffed, etc. But one point I think you missed is the part where I mentioned, "I'm reviewing code of a colleague". :) (In fact this isn't even my part of the project; I merely introduced jOOQ and then handed it over to my colleague. Now I'm doing a code review.)
...Well, I still don't know how you created that DataSource and I thus don't know why you're assuming that it is creating a new Connection every time for jOOQ. It might be. But that's the DataSource's responsibility, not jOOQ's. So again, how *did* you implement that DataSource? (And why don't you use some connection pool?)
The other part you may have missed is that the exact configuration is hypothetical, removing all other variables (such as connection pooling, etc.) just so that I can understand how jOOQ works and fully evaluate my colleague's code.
The main point I was trying to make is the following: the only way my colleague's code works with jOOQ after setting autocommit manually on a manually-retrieved connection, is that my colleague's code passes around the connection and forms new DSLContext instances directly from that connection.
If this code were to instead create new DSLContext instances from the jOOQ configuration (which in turn is formed directly from the data source, as per my hypothetical code at the start of this thread), for each command those new DSLContext instances would request anew a connection directly from the data source, which isn't guaranteed to be the connection on which autocommit was set (and which isn't part of the transaction), so that wouldn't work.
So I understand jOOQ (and indeed Spring and JavaEE and ULTM) connection usage much better now from this discussion by considering this hypothetical configuration. Thanks for bearing with me; it was very helpful.
...
Yes, the project is in too much of a hurry and it's understaffed, etc. But one point I think you missed is the part where I mentioned, "I'm reviewing code of a colleague". :) (In fact this isn't even my part of the project; I merely introduced jOOQ and then handed it over to my colleague. Now I'm doing a code review.)
Yeah, I got that part and I smirked. It's always "them colleagues", right?
;-)