Generated DAO has flexibility to customize RecordMapper but not DSLContext

90 views
Skip to first unread message

sachint...@gmail.com

unread,
Oct 8, 2015, 5:05:07 PM10/8/15
to jOOQ User Group
Hello all,

I am new here so please forgive if I am not really clear on my question or I have missed any important details.

I am trying to integrate Ninja Framework and JOOQ using guice-persist-jooq, I created a Postgres DB and generated various classes(DAO, Model, Pojo etc) using jooq-codegen I noticed that the generated DAO always create a new DSLContext in using() method in DAOImpl. I am planing to inject DSLContext using guice and use it somehow in generated DAOs. I could not find any way. Could you please help.

Thanks,
Sachin

Lukas Eder

unread,
Oct 9, 2015, 4:50:33 AM10/9/15
to jooq...@googlegroups.com
Hello Sachin,

DSLContext doesn't really have a lifecycle (or state) of its own. It's just a wrapper for org.jooq.Configuration, which contains all the interesting stuff, enhancing it with DSL entry points - just like the static DSL utility class. As such, it doesn't matter that it is generated afresh all the time.

Generated DAOs have a constructor that accepts a Configuration. Or, you can use DAOImpl.setConfiguration().

I hope this helps,
Lukas

--
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.

sachint...@gmail.com

unread,
Oct 11, 2015, 4:11:11 AM10/11/15
to jOOQ User Group
Hi Lukas,

Thanks for your swift reply. I apologize for not being much clear in the question. I do not have any problem with DSLContext being generated afresh every time. The concern I have is that the generation of DSLContext is now rigid and cannot be extended to any other generation pattern. e.g to use a decorator instead. guice-persist-jooq gives a way to inject DSLContext to any class. So just while guice binding, I can choose which implementation I want to use (https://github.com/supercargo/guice-persist-jooq). If this flexibility, to pass the intended implementation as an overridden method result or any other mechanism, could be implemented, then I won't need to modify the generated DAO code much. If this is not possible or too much impact, then I always have an option to inject the configuration instead, I guess.

And lastly, Thank you for this awesome library. It really is a wonderful way out for the guys like me to whom JPA seems to be an overkill.

Thanks,
Sachin 

Lukas Eder

unread,
Oct 12, 2015, 11:51:21 AM10/12/15
to jooq...@googlegroups.com
Hi Sachin,

Thanks for the additional explanation. You're right, the generation of a DSLContext instance within DAOImpl is "rigid". But overriding it doesn't sound like something we'd expect or want our users to be doing. May I ask you to explain what you'd like to achieve with this overriding? Do you want to tweak the generated SQL statements? Perhaps there's an interesting feature request hidden in there, somewhere, perhaps not even related to DAOs.

And thanks for your nice words.

Cheers,
Lukas

sachint...@gmail.com

unread,
Oct 12, 2015, 12:23:23 PM10/12/15
to jOOQ User Group
Hi Lukas,

I was just thinking if there is any way to provide DSLContext instead of creating it in DAO. But as you suggested, I can always use configuration to inject in the DAO. I will use this approach now.

And I have a small query.

sachint...@gmail.com

unread,
Oct 12, 2015, 12:26:25 PM10/12/15
to jOOQ User Group
Hi Lukas,

My query is, can I directly use the generated DAO in production environment.

Thanks,
Sachin

Lukas Eder

unread,
Oct 14, 2015, 11:22:52 AM10/14/15
to jooq...@googlegroups.com
Hi Sachin,

Well, yes you can do that. The generated DAO just links the generated Table to the generated POJO type, and adds some convenience methods for fetching.

What is the concern you are having? I mean, why did you think there might be a risk in doing so?

Cheers,
Lukas


Thanks,
Sachin

--
You received this message because you are subscribed to the Google Groups "jOOQ User Group" group.

jens.kl...@gmail.com

unread,
Oct 22, 2015, 5:43:24 AM10/22/15
to jOOQ User Group
I don't know if this helps or if it's a best practice, but I extended the JavaGenerator to inject the Configuration. Sadly setConfiguration in DaoImpl is final so I had to create a new method for all DAOs. Here is the Generator-Class:

public class InjectConfigurationGenerator extends JavaGenerator {

    @Override
    protected void generateDaoClassFooter(TableDefinition table, JavaWriter out) {
        super.generateDaoClassFooter(table, out);
        out.tab(1).println("@com.google.inject.Inject");
        out.tab(1).println("public void injectConfiguration(Configuration configuration) {");
            out.tab(2).println("super.setConfiguration(configuration);");
        out.tab(1).println("}");
    }

    @Override
    protected void printClassAnnotations(JavaWriter out, SchemaDefinition schema) {
        super.printClassAnnotations(out, schema);
        if(out.file().getName().contains("Dao")){
            out.println("@%s", "com.google.inject.Singleton");
        }
    }

}

Has anyone a better idea how to implement this properly?

Lukas Eder

unread,
Oct 26, 2015, 11:07:27 AM10/26/15
to jooq...@googlegroups.com
I'm not sure how Guice works in detail, but could you, perhaps, inject the configuration via the constructor instead?

Note that we've had a lot of feedback about "final" on methods in DAOImpl. It appears that our "best practice" of closing our implementation from the outside is mostly criticised in this context, where - apparently - we did something wrong in our design of this particular class. I suspect that for the time being, it may be useful for users to be able to override behaviour in their implementations, even if we prefer discussing things to come to a better API.

Thus, I've created this feature request for jOOQ 3.8:

Best Regards,
Lukas

Sachin Taksande

unread,
Oct 26, 2015, 12:03:20 PM10/26/15
to jooq...@googlegroups.com

I have done the same Lukas. After the DAO is generated, I just annotate the constructor with parameterized configuration as @Inject. Also, I have defined a provider to use a Singleton Configuration. It is working for me. I can post the code if you want but the code is very basic.

Thanks,
Sachin

You received this message because you are subscribed to a topic in the Google Groups "jOOQ User Group" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/jooq-user/-4FMMKajTv0/unsubscribe.
To unsubscribe from this group and all its topics, send an email to jooq-user+...@googlegroups.com.

jens.kl...@gmail.com

unread,
Oct 27, 2015, 4:46:44 AM10/27/15
to jOOQ User Group
So my first attempt was to create my own GeneratorStrategy and overwrite 

  • DefaultGeneratorStrategy.getJavaClassExtends(Definition, Mode)  (org.jooq.util)

but for some reason this does not get called for DAOs. Even if this would have been possible, because setConfiguration is final, I wouldn't be able to overwrite and annotate the method. I agree it would have been the best to annotate the constructor, but there is no method in the JavaGenerator that I can overwrite. I've found 

if (generateSpringAnnotations())
            out.println("@%s", out.ref("org.springframework.stereotype.Repository"));

which adds an annotation to the constructor. Maybe this can be rewritten and extracted into a protected method writeConstructorAnnotations or something? I could then overwrite that method and add my annotations to inject the configuration via constructor so there is no need to remove the final keyword from setConfiguration. 

Great (frame) work btw!

Lukas Eder

unread,
Oct 27, 2015, 5:58:43 AM10/27/15
to jooq...@googlegroups.com
2015-10-27 9:46 GMT+01:00 <jens.kl...@gmail.com>:
So my first attempt was to create my own GeneratorStrategy and overwrite 

  • DefaultGeneratorStrategy.getJavaClassExtends(Definition, Mode)  (org.jooq.util)

but for some reason this does not get called for DAOs.

The original rationale is that most types (except for POJOs and jOOQ 3.8 domains) depend on an internal base implementation, e.g. TableImpl, UpdatableRecordImpl, DAOImpl. In many of these cases, the base implementation is required in jOOQ's internals. Thus far, we haven't seen the need for changing that.

Of course, it might seem useful at first, as additional functionality can be patched into generated classes very easily. But the effort to document and maintain the additional requirements that evolve from this (e.g. your "extends" class MUST extend DAOImpl, etc.) are a sign that we would be creating too much complexity here.
 
Even if this would have been possible, because setConfiguration is final, I wouldn't be able to overwrite and annotate the method. I agree it would have been the best to annotate the constructor, but there is no method in the JavaGenerator that I can overwrite. I've found 

if (generateSpringAnnotations())
            out.println("@%s", out.ref("org.springframework.stereotype.Repository"));

which adds an annotation to the constructor. Maybe this can be rewritten and extracted into a protected method writeConstructorAnnotations or something? I could then overwrite that method and add my annotations to inject the configuration via constructor so there is no need to remove the final keyword from setConfiguration.

That's correct. However (and I'm sorry if I sound like giving excuses all the time), it is far from trivial to factor out *useful* code generation extensions that are:

- Easy to document
- Obvious to discover
- Easy for us and you to maintain
- Forward-looking

There's a huge task in jOOQ 4.0 to improve (probably rewrite) the code generator. Before that, I'm very wary of adding new features. It's probably easier right now for you to just override the generateDao() method, and roll your own.

Nonetheless, very good to hear feedback. Especially the DAO area is apparently not good enough compared to what users need.
 
Great (frame) work btw!

Thank you :)
Reply all
Reply to author
Forward
0 new messages