Git Product home page Git Product logo

vertx-jooq's Introduction

vertx-jooq

A jOOQ-CodeGenerator to create vertx-ified DAOs and POJOs! Perform all CRUD-operations asynchronously and convert your POJOs from/into a io.vertx.core.json.JsonObject using the API and driver of your choice.

latest release 6.5.5

  • Fix Use enum literal instead of toString for datatype conversion #209
  • Update to jooq 3.17.3
  • Update to vertx 4.3.3
  • Update mutiny dependencies
  • Update rx dependencies

different needs, different apis

What do you want

Before you start generating code using vertx-jooq, you have to answer these questions:

  • Which API do you want to use?
    • a io.vertx.core.Future-based API. This is vertx-jooq-classic.
    • a rxjava2 based API. This is vertx-jooq-rx.
    • a rxjava3 based API. This is vertx-jooq-rx3.
    • a mutiny based API. This is vertx-jooq-mutiny.
  • How do you want to communicate with the database?
    • Using good old JDBC, check for the modules with -jdbc suffix.
    • Using the reactive vertx database driver, check for -reactive modules.
  • Do you need extras?
    • Support for Guice dependency injection
    • Generation of io.vertx.codegen.annotations.@DataObject-annotations for your POJOs

Once you made your choice, you can start to configure the code-generator. This can be either done programmatically or using a maven- / gradle-plugin (recommended way). Please check the documentation in the module of the API and driver of your choice how to set it up and how to use it:

example

Once the generator is set up, it can create DAOs like in the code snippet below (classic-API, JDBC, no dependency injection):

//Setup your jOOQ configuration
Configuration configuration = ...

//setup Vertx
Vertx vertx = Vertx.vertx();

//instantiate a DAO (which is generated for you)
SomethingDao dao = new SomethingDao(configuration,vertx);

//fetch something with ID 123...
dao.findOneById(123)
    .onComplete(res->{
    		if(res.succeeded()){
        		vertx.eventBus().send("sendSomething", res.result().toJson())
    		}else{
    				System.err.println("Something failed badly: "+res.cause().getMessage());
    		}
    });

//maybe consume it in another verticle
vertx.eventBus().<JsonObject>consumer("sendSomething", jsonEvent->{
    JsonObject message = jsonEvent.body();
    //Convert it back into a POJO...
    Something something = new Something(message);
    //... change some values
    something.setSomeregularnumber(456);
    //... and update it into the DB
    Future<Integer> updatedFuture = dao.update(something);
});

//or do you prefer writing your own type-safe SQL? Use the QueryExecutor from the DAO...
ClassicQueryExecutor queryExecutor = dao.queryExecutor();
//... or create a new one when there is no DAO around :)
queryExecutor = new JDBCClassicGenericQueryExecutor(configuration,vertx);
Future<Integer> updatedCustom = queryExecutor.execute(dslContext ->
				dslContext
				.update(Tables.SOMETHING)
				.set(Tables.SOMETHING.SOMEREGULARNUMBER,456)
				.where(Tables.SOMETHING.SOMEID.eq(something.getSomeid()))
				.execute()
);

//check for completion
updatedCustom.onComplete(res->{
		if(res.succeeded()){
				System.out.println("Rows updated: "+res.result());
		}else{
				System.err.println("Something failed badly: "+res.cause().getMessage());
		}
});

More examples can be found here, here and here.

FAQ

vertx is cool, but what about quarkus?

Checkout this repository to figure out how to utilize vertx-jooq to create Quarkus-compatible classes.

handling custom datatypes

The generator will omit datatypes that it does not know, e.g. java.sql.Timestamp. To fix this, you can subclass the generator, handle these types and generate the code using your generator. See the handleCustomTypeFromJson and handleCustomTypeToJson methods in the AbstractVertxGenerator or checkout the CustomVertxGenerator from the tests.

is vertx-jooq compatible with Java 8?

Starting with version 6.4.0, vertx-jooq implicitly requires Java 11, as this is the minimum required version by the non-commercial version of jOOQ 3.15. If you're stuck with Java 8, the latest version you can use is 6.3.0.

are you sure this works?

Yes! There are many integration tests that cover most usecases. Check them out if you're interested.

how to run tests

The tests are executed against two docker containers. Please refer to this readme of how to set them up.

I receive a "Too many open files" exception on macOS

Increase your file limits. Unfortunately the solution differs by each OS version, so you have to do some research.

disclaimer

This library comes without any warranty - just take it or leave it. Also, the author is neither connected to the company behind vertx nor the one behind jOOQ.

vertx-jooq's People

Contributors

bentatham avatar cdekok avatar cescoffier avatar dependabot[bot] avatar doctorpangloss avatar dreamkidd avatar guss77 avatar jamieps avatar jasminsuljic avatar jklingsporn avatar jotschi avatar m1schka avatar mykelalvis avatar oresoftware avatar quen2404 avatar romanbsd avatar ukonnra avatar weisslertal avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vertx-jooq's Issues

Create complex request

Hi,
it should be nice if we could use dao to make complex requests like group by, or join. Because, currently we have to redevelop the wrapper between JooQ and sql driver.
What do you think ?

Compile errors in generated code - "import java.util.List" missing

The generated code has a reference to the java.util.List class but there are no corresponding import statements resulting in a compile error. Here's a snippet of the generated code

public class ParentDao extends AbstractVertxDAO<ParentRecord, Parent, String, Single<List<Parent>>, Single<Optional<Parent>>, Single<Integer>, Single<String>> implements io.github.jklingsporn.vertx.jooq.rx.VertxDAO<ParentRecord,Parent,String> {

I'm using vertx-jooq-rx-jdbc and all jars are v3.1.0. I do notice that this issue is not present in all generated DAO's. E.g. the below code is fine and the generated code is practically identical.

public class ChildDao extends AbstractVertxDAO<ChildRecord, Child, String, Single<List<Child>>, Single<Optional<Child>>, Single<Integer>, Single<String>> implements io.github.jklingsporn.vertx.jooq.rx.VertxDAO<ChildRecord,Child,String> {

Perhaps, if someone can point me to where to look within the source files, I can try to figure out what's so special in the first scenario.

Make GeneratorStrategy pluggable

Currently a user is forced to use the VertxGeneratorStrategy which extends DefaultGeneratorStrategy. This makes it hard to plug-in custom user strategies or the ones provided by jooq. To fix this, make VertxGeneratorStrategy use delegation and allow users to plug-in their own GeneratorStrategy.

JDBC

Why the JDBC version doesn't use https://vertx.io/docs/vertx-jdbc-client/java/ ?

Enums get generated without the `getCatalog()` call

Using vertx-jooq from the current master causes us to load jOOQ 3.9.2, in which the EnumType interface specifies a method getCatalog() to be implemented, but when I run the vertx-jooq-future code generator, it generates enum types without the getCatalog() method - and then compilation fails.

From looking at the jOOQ code, it looks like getCatalog() (and its supporting generator code) was introduced between jOOQ 3.8.4 and 3.8.6. Is it possible that the generator is still using the old jOOQ version while the runtime uses the new one?

Here's the output of my mvn dependency:tree :

[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ apicore ---
[INFO] my.organization:project:jar:0.1.0
[INFO] +- my.organization:support-vertx:jar:0.4.1:compile
[INFO] |  \- io.vertx:vertx-web:jar:3.4.1:compile (version selected from constraint [3,))
[INFO] |     \- io.vertx:vertx-auth-common:jar:3.4.1:compile
[INFO] +- io.vertx:vertx-core:jar:3.4.1:compile
[INFO] |  +- io.netty:netty-common:jar:4.1.8.Final:compile
[INFO] |  +- io.netty:netty-buffer:jar:4.1.8.Final:compile
[INFO] |  +- io.netty:netty-transport:jar:4.1.8.Final:compile
[INFO] |  +- io.netty:netty-handler:jar:4.1.8.Final:compile
[INFO] |  |  \- io.netty:netty-codec:jar:4.1.8.Final:compile
[INFO] |  +- io.netty:netty-handler-proxy:jar:4.1.8.Final:compile
[INFO] |  |  \- io.netty:netty-codec-socks:jar:4.1.8.Final:compile
[INFO] |  +- io.netty:netty-codec-http:jar:4.1.8.Final:compile
[INFO] |  +- io.netty:netty-codec-http2:jar:4.1.8.Final:compile
[INFO] |  +- io.netty:netty-resolver:jar:4.1.8.Final:compile
[INFO] |  +- io.netty:netty-resolver-dns:jar:4.1.8.Final:compile
[INFO] |  |  \- io.netty:netty-codec-dns:jar:4.1.8.Final:compile
[INFO] |  +- com.fasterxml.jackson.core:jackson-core:jar:2.7.4:compile
[INFO] |  \- com.fasterxml.jackson.core:jackson-databind:jar:2.7.4:compile
[INFO] |     \- com.fasterxml.jackson.core:jackson-annotations:jar:2.7.0:compile
[INFO] +- com.google.dagger:dagger:jar:2.11-rc2:compile
[INFO] |  \- javax.inject:javax.inject:jar:1:compile
[INFO] +- com.google.dagger:dagger-compiler:jar:2.11-rc2:compile
[INFO] |  +- com.google.dagger:dagger-producers:jar:2.11-rc2:compile
[INFO] |  +- com.google.code.findbugs:jsr305:jar:3.0.1:compile
[INFO] |  +- com.google.googlejavaformat:google-java-format:jar:1.3:compile
[INFO] |  |  \- com.google.errorprone:javac:jar:9-dev-r3297-1-shaded:compile
[INFO] |  +- com.google.guava:guava:jar:21.0:compile
[INFO] |  \- com.squareup:javapoet:jar:1.7.0:compile
[INFO] +- junit:junit:jar:4.12:test
[INFO] |  \- org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] +- io.vertx:vertx-unit:jar:3.4.1:test
[INFO] +- org.slf4j:slf4j-jdk14:jar:1.8.0-alpha2:compile
[INFO] |  \- org.slf4j:slf4j-api:jar:1.8.0-alpha2:compile
[INFO] +- io.github.jklingsporn:vertx-jooq:jar:fd34d8ee7b:compile
[INFO] |  +- io.github.jklingsporn.vertx-jooq:vertx-jooq-classic:jar:fd34d8ee7b:compile
[INFO] |  |  \- org.jooq:jooq:jar:3.9.2:compile
[INFO] |  +- io.github.jklingsporn.vertx-jooq:vertx-jooq-future:jar:fd34d8ee7b:compile
[INFO] |  |  \- me.escoffier.vertx:vertx-completable-future:jar:0.1.1:compile
[INFO] |  +- io.github.jklingsporn.vertx-jooq:vertx-jooq-generate:jar:fd34d8ee7b:compile
[INFO] |  |  \- org.jooq:jooq-codegen:jar:3.9.2:compile
[INFO] |  |     \- org.jooq:jooq-meta:jar:3.9.2:compile
[INFO] |  \- io.github.jklingsporn.vertx-jooq:vertx-jooq-shared:jar:fd34d8ee7b:compile
[INFO] +- mysql:mysql-connector-java:jar:6.0.6:compile
[INFO] \- com.github.cescoffier:vertx-completable-future:jar:vertx-completable-future-0.1.2:compile

java.time.LocalDateTime in JsonObject during update

Hi,
i have currently an issue when i'm trying to update one entity. It's a row of a simple SQL table:

-- auto-generated definition
CREATE TABLE channel
(
  uid           INT AUTO_INCREMENT PRIMARY KEY,
  external_id   VARCHAR(255)                                                 NOT NULL,
  extenal_href  VARCHAR(255)                                                 NOT NULL,
  name          VARCHAR(255)                                                 NULL,
  status        ENUM ('ACTIVE', 'SUSPENDED', 'DEACTIVATED') DEFAULT 'ACTIVE' NOT NULL,
  data          LONGTEXT                                                     NULL,
  creation_date DATETIME DEFAULT CURRENT_TIMESTAMP                           NOT NULL
)
  ENGINE = InnoDB;

to use java.time classes, i'm using this option in maven generator configuration:

            <plugin>
                <configuration>
                    <generator>
                        <generate>
                            <!-- ... -->
                            <javaTimeTypes>true</javaTimeTypes>
                        </generate>
                    </generator>
                </configuration>
            </plugin>

and i'm using this custom generator.

Here is my code:

        channelDao.findOneByCondition(CHANNEL.UID.eq(1)).setHandler(result -> {
            if (result.succeeded()) {
                Channel channel = result.result();
                channel.setName("TEST");
                channelDao.update(channel).setHandler(resultUpdate -> {
                    if (!resultUpdate.succeeded()) {
                        LOG.error("UPDATE exception", resultUpdate.cause());
                    }
                });
            } else {
                LOG.error("GET exception", result.cause());
            }
        });

The stack trace:

2018-02-23 14:56:25.461 [vert.x-eventloop-thread-1] ERROR com.actility.thingpark.enterprise.channel.portal.controller.operator.ChannelController - UPDATE exception
java.lang.IllegalStateException: Illegal type in JsonObject: class java.time.LocalDateTime
	at io.vertx.core.json.Json.checkAndCopy(Json.java:210) ~[vertx-core-3.5.1.jar:3.5.1]
	at io.vertx.core.json.JsonArray.add(JsonArray.java:439) ~[vertx-core-3.5.1.jar:3.5.1]
	at io.github.jklingsporn.vertx.jooq.shared.internal.async.AbstractAsyncQueryExecutor.getBindValues(AbstractAsyncQueryExecutor.java:56) ~[vertx-jooq-shared-3.0.0.jar:?]
	at io.github.jklingsporn.vertx.jooq.classic.async.AsyncClassicGenericQueryExecutor.lambda$execute$0(AsyncClassicGenericQueryExecutor.java:38) ~[vertx-jooq-classic-async-3.0.0.jar:?]
	at io.vertx.core.Future.lambda$compose$1(Future.java:265) ~[vertx-core-3.5.1.jar:3.5.1]
	at io.vertx.core.impl.FutureImpl.tryComplete(FutureImpl.java:121) ~[vertx-core-3.5.1.jar:3.5.1]
	at io.vertx.core.impl.FutureImpl.complete(FutureImpl.java:83) ~[vertx-core-3.5.1.jar:3.5.1]
	at io.vertx.core.impl.FutureImpl.handle(FutureImpl.java:147) ~[vertx-core-3.5.1.jar:3.5.1]
	at io.vertx.core.impl.FutureImpl.handle(FutureImpl.java:18) ~[vertx-core-3.5.1.jar:3.5.1]
	at io.vertx.ext.asyncsql.impl.BaseSQLClient.lambda$getConnection$0(BaseSQLClient.java:72) ~[vertx-mysql-postgresql-client-3.5.1.jar:3.5.1]
	at io.vertx.ext.asyncsql.impl.pool.AsyncConnectionPool.lambda$createConnection$0(AsyncConnectionPool.java:69) ~[vertx-mysql-postgresql-client-3.5.1.jar:3.5.1]
	at io.vertx.ext.asyncsql.impl.ScalaUtils$3.apply(ScalaUtils.java:91) ~[vertx-mysql-postgresql-client-3.5.1.jar:3.5.1]
	at io.vertx.ext.asyncsql.impl.ScalaUtils$3.apply(ScalaUtils.java:87) ~[vertx-mysql-postgresql-client-3.5.1.jar:3.5.1]
	at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:60) ~[scala-library-2.12.4.jar:?]
	at io.vertx.ext.asyncsql.impl.VertxEventLoopExecutionContext.lambda$execute$0(VertxEventLoopExecutionContext.java:59) ~[vertx-mysql-postgresql-client-3.5.1.jar:3.5.1]
	at io.vertx.core.impl.ContextImpl.lambda$wrapTask$2(ContextImpl.java:339) ~[vertx-core-3.5.1.jar:3.5.1]
	at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163) [netty-common-4.1.19.Final.jar:4.1.19.Final]
	at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:404) [netty-common-4.1.19.Final.jar:4.1.19.Final]
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:463) [netty-transport-4.1.19.Final.jar:4.1.19.Final]
	at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:886) [netty-common-4.1.19.Final.jar:4.1.19.Final]
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) [netty-common-4.1.19.Final.jar:4.1.19.Final]
	at java.lang.Thread.run(Thread.java:745) [?:1.8.0_92]

I don't understand why it doesn't works. I have no problem in my code when i'm retrieving or creating an entity.

Using the new reactive pg driver with a limit clause throws a ClassCastException

I'm currently experimenting with the new reactive PostgreSQL driver: io.github.jklingsporn:vertx-jooq-classic-reactive:4.0.0-BETA.

Executing the following query without a limit clause is working:

queryExecutor.execute(dslContext -> dslContext.selectFrom(EXCHANGE))

While executing the following statement throws an exception:

queryExecutor.execute(dslContext -> dslContext.selectFrom(EXCHANGE).limit(2))

SEVERE: Unhandled exception
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Long
	at io.reactiverse.pgclient.impl.codec.DataType$7.encodeBinaryInternal(DataType.java:222)
	at io.reactiverse.pgclient.impl.codec.DataType.encodeBinary(DataType.java:1059)
	at io.reactiverse.pgclient.impl.codec.encoder.message.Bind.encode(Bind.java:154)
	at io.reactiverse.pgclient.impl.codec.encoder.message.Bind.encode(Bind.java:167)
	at io.reactiverse.pgclient.impl.SocketConnection.checkPending(SocketConnection.java:210)
	at io.reactiverse.pgclient.impl.SocketConnection.bilto(SocketConnection.java:191)
	at io.reactiverse.pgclient.impl.CommandBase.foo(CommandBase.java:54)
	at io.reactiverse.pgclient.impl.SocketConnection.schedule(SocketConnection.java:181)
	at io.reactiverse.pgclient.impl.ConnectionPool$PooledConnection.schedule(ConnectionPool.java:81)
	at io.reactiverse.pgclient.impl.PgPoolImpl$1.lambda$onSuccess$0(PgPoolImpl.java:73)
	at io.vertx.core.impl.ContextImpl.lambda$wrapTask$2(ContextImpl.java:339)
	at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163)
	at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:404)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:463)
	at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:886)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.lang.Thread.run(Thread.java:748)

QueryExecutor API changes

The QueryExecutor has some questionable design-choices:

  • consider changing all methods from taking something extends org.jooq.Query to Function<org.jooq.Query,XYZ>. Calling the QueryExecutor directly will change from
queryExecutor.findOne(DSL.using(configuration).selectFrom(Foo).where(DSL.trueCondition()))

to

queryExecutor.findOne(dslContenxt -> dslContext.selectFrom(Foo).where(DSL.trueCondition()))

Callers then don't have to carry around a org.jooq.Configuration any longer.

  • as a consequence store a org.jooq.Configuration in QueryExecutor instead of AbstractDAO. AbstractDao#getConfiguration should then forward to the executor.

QueryExecutors of one API should share same method signature

Consider creating custom (detached) Record implementations for -async and -reactive QueryExecutors so we can have an API like this (here: CompletableFuture)

public interface CompletableFutureQueryExecutor {

    public CompletableFuture<Integer> execute(Function<DSLContext,Query> queryFunction);

    public <R extends Record> CompletableFuture<R> findOneRaw(Function<DSLContext,ResultQuery<R>> queryFunction);

    public <R extends Record> CompletableFuture<List<R>> findManyRaw(Function<DSLContext,ResultQuery<R>> queryFunction);

}

Naming-suggestions JsonObjectRecord for async and RowObjectRecord for reactive.
Then one can easily switch between drivers.

Enum type cannot be used in async driver

Scala does not know how to handle the enum type so it has to be converted into a String.

cala.MatchError: ACTIVE (of class com.actility.thingpark.enterprise.channel.portal.storage.enums.ChannelStatus)
	at com.github.mauricio.async.db.mysql.binary.BinaryRowEncoder.encoderFor(BinaryRowEncoder.scala:88) ~[mysql-async_2.12-0.2.21.jar:0.2.21]
	at com.github.mauricio.async.db.mysql.encoder.PreparedStatementExecuteEncoder.encodeValue(PreparedStatementExecuteEncoder.scala:78) ~[mysql-async_2.12-0.2.21.jar:0.2.21]
	at com.github.mauricio.async.db.mysql.encoder.PreparedStatementExecuteEncoder.encodeValues(PreparedStatementExecuteEncoder.scala:61) ~[mysql-async_2.12-0.2.21.jar:0.2.21]
	at com.github.mauricio.async.db.mysql.encoder.PreparedStatementExecuteEncoder.encode(PreparedStatementExecuteEncoder.scala:39) ~[mysql-async_2.12-0.2.21.jar:0.2.21]
	at com.github.mauricio.async.db.mysql.codec.MySQLOneToOneEncoder.encode(MySQLOneToOneEncoder.scala:75) ~[mysql-async_2.12-0.2.21.jar:0.2.21]
	at com.github.mauricio.async.db.mysql.codec.MySQLOneToOneEncoder.encode(MySQLOneToOneEncoder.scala:35) ~[mysql-async_2.12-0.2.21.jar:0.2.21]
	at io.netty.handler.codec.MessageToMessageEncoder.write(MessageToMessageEncoder.java:88) ~[netty-codec-4.1.19.Final.jar:4.1.19.Final]
	... 35 more

`toJson()` crashes when converting an enum type with a null value

When calling toJson() on a Pojo with a nullable enum field (or a just created object), an NPE is thrown from the call to getLiteral() on the null value.

Likely introduced by the fix in 6f1a44b to issue #14 .

My workaround was to implement handleCustomTypeToJson() like this:

@Override
protected boolean handleCustomTypeToJson(TypedElementDefinition<?> column, String getter, String columnType, String javaMemberName, JavaWriter out) {
    if(column.getDatabase().getEnum(column.getSchema(), column.getType().getUserType()) != null) { // isEnum() from AbstractVertxGenerator
        out.ref("org.jooq.EnumType");
        out.ref("java.util.Optional");
        out.tab(2).println("json.put(\"%s\",Optional.ofNullable(%s()).map(EnumType::getLiteral).orElse(null));", javaMemberName, getter);
        return true;
    }
    return false;
}

I can offer this as a patch to the the AbstractVertxGenerator if you want.

Move away from GeneratorStrategies to generate DAOs

According to the Docs, a jOOQ-GeneratorStrategy is used

for naming various artefacts generated from Definition's

so we should move the logic from the strategies into subclasses of VertxGenerator so one can keep using it's own strategies.
To reduce code-duplication we should use some builder-pattern to generate the different variants: API-Type, Driver-Type, Injection-support.

RowMappers.java created in different directory

Using 4.0-beta along with VertxGeneratorStrategy for code generation. The code executes fine but when I look at the generated DAO code, I see a reference to org.jooq.generated.tables.mappers.RowMappers class in the DAO constructor, which is missing. Upon debugging, I see that the class is being generated but in a different directory instead of honoring the target directory (relative path in my case "../generated/src/main/java") as specified in the configuration file - https://www.jooq.org/doc/3.10/manual/code-generation/codegen-advanced/codegen-config-target/. To be clear all other files (pojos, daos etc.) are being generated in the specified target directory. It's only the RowMappers.java that is not. I suspect the relative path is tripping the code during initialization of the target directory.

Several methods of VertxDao can fail silently

Example:

default CompletableFuture<Void> insertAsync(P object) {
        return FutureTool.executeBlocking(h->{insert(object);h.complete();},vertx());
    }

If insert(object); fails for whatever reason, the exception is swallowed without being properly forwarded to the future.

Support for routines - 3.1 branch

Dear @jklingsporn and @quen2404 ,

Would it be possible to add support for routines? Seems like currently, you have to pass it jooq configuration object to make this work.

  1. Can AsyncClient use the configuration object to obtain connection?
  2. I have implemented row-level-security, so i have to share the connection between (pre-and-post) routine and DAO. Is there a way to execute routines by chaining pre and post of DAO?

Appreciate your response to the question and request in advance.

Regards,
Pratik Parikh

We need a proper wiki

  • explain the different modules
  • configuration of the generator
  • add example for handling custom types
  • add example for changing JSON key names

Default values not respected

Seems like default values are not respected when I perform an insert like so:

userDao.insert(user).handleAsync { ... }

Strangely, if I use the SQL builder wrapped in a vertx.executeBlocking, default values are subsequently inserted properly:

val got = dsl.insertInto(USER, USER.EMAIL, USER.PASSWORD).values(email, password)

I assume that this is related to the setDefault method in AbstractVertxDAO, but I'm not entirely sure that's where the problem lies.


Postgres: 10.2
Vertx-jooq version: 3.0.1
Vertx-jooq flavour: completablefuture-async

When using enum values that are not Java names, `fromJson()` rejects such values

The problem is that fromJson uses Enum.valueOf() to get the correct enum value generated by the Jooq Java generator, which in turn "normalizes" the values from the database to Java names (otherwise the enum won't compile, obviously).

So in my case, my field looks like this:

  `direction` ENUM('inbound', 'outbound', 'public-inbound') NOT NULL,

which Jooq generates to:

public enum TableDirection implements EnumType {
    inbound("inbound"),
    outbound("outbound"),
    public_inbound("public-inbound");

Now when I pass the JSON value {"direction": "public-inbound"} I get an exception, while {"direction": "public_inbound"} works fine.

The way I see it, fromJson() should lookup the actual text value of the enum instead of the normalized Java name.

the generated code appear compile error

the dao class got there is no default constructor avaliable in 'org.jooq.impl.DAOImpl'

and the pojo class has a default method in Pojo Class

just like this

default ISysUser fromJson(io.vertx.core.json.JsonObject json) {
        setId(json.getInteger("id"));
        setUserName(json.getString("user_name"));
 ...
    }

i wonder know what can cause this

class AsyncJooqSQLClient missing

The usage section at the end of the Readme.md in vertx-jooq-classic-async lists

AsyncJooqSQLClient client = AsyncJooqSQLClient.create(vertx,MySQLClient.createNonShared(vertx, config))

but I cannot find class AsyncJooqSQLClient anywhere.

This might be either a bug in the docs or an omission due to the move from the separate async repository into this repository.

Retrieve auto-incremented primary key after insert

I am using vertx-jooq-classic-async with PostgreSQL. I'm currently looking for a way to retrieve the primary key of a newly inserted row.

I first attempted to do this by using the AsyncClassicGenericQueryExecutor. However, it seems as the query executor only returns the number of affected rows.

I then tried to use the insertReturningPrimary method of the corresponding DAO. However, this feature is currently not supported for PostgreSQL.

Normally, I'd just use the generated Record class to insert a new entity, due to the fact that the id field of the record is updated after the insert. However, it doesn't seem as if Records are supported, since there is no way to provide a client connection.

Am I missing something or is it currently not possible to retrieve the primary key when using PostgreSQL?

Vertx JOOQ not doing rollback with HikariCPdatasource in configuration object

With Hikaricpdatasource in Configuration object, for a transaction having multiple operations, it must do rollback if any of the operations fails.

Configure Configuration object with HikariCP datasource and do a transaction using JOOQ query with this configuration.

public static Configuration getConfiguration() throws SQLException {

    return new DefaultConfiguration().set(SQLDialect.POSTGRES) 
           .set(HikariCPDataSource.getDataSource());
}

public static void testDB() throws SQLException {
Vertx vertx = Vertx.vertx();
AuthorDao dao = new AuthorDao(configuration);
dao.setVertx(vertx);
dao.executeAsync(dslContext -> {
CompletionStage stage = dslContext.transactionAsync(
action -> {
Object result = dslContext.insertInto(Tables.AUTHOR, Tables.AUTHOR.AUTHOR.ID, Tables.AUTHOR.AUTHOR.NAME)
.values("3", "3").execute();
result = dslContext.update(Tables.AUTHOR).set(Tables.AUTHOR.NAME, "-1").where(Tables.AUTHOR.ID.eq("0")).execute();
throwException(); //throwing an exception explicitly.
});
stage.thenApply(t -> {
try {
// connection.close();
} catch (Exception e) {}
return null;
});
return "SUCCESS";
},///CLOVER:OFF
handler -> {
if (handler.failed()) {
System.out.println("failed");
} else {
System.out.println("Passed");
}
});

}

Versions:

  • jOOQ: 3.10.2
    -vertx: 3.2.0
  • Java: 1.8
  • Database (include vendor): Postgres

ArrayIndexOutOfBoundsException when using custom code generator strategy

I'm using the 4.0-beta version. If I have a custom code generator strategy, attached, I get the following error:

[ERROR] Error while generating table DAO public.<table name>
java.lang.ArrayIndexOutOfBoundsException: 1
	at io.github.jklingsporn.vertx.jooq.generate.builder.VertxGeneratorBuilder$ExecutionStepImpl.lambda$withPostgresReactiveDriver$30(VertxGeneratorBuilder.java:378)
	at io.github.jklingsporn.vertx.jooq.generate.builder.ComponentBasedVertxGenerator.writeDAOConstructor(ComponentBasedVertxGenerator.java:81)
	at io.github.jklingsporn.vertx.jooq.generate.builder.DelegatingVertxGenerator.writeDAOConstructor(DelegatingVertxGenerator.java:63)
	at io.github.jklingsporn.vertx.jooq.generate.VertxGenerator.generateDAO(VertxGenerator.java:542)
	at io.github.jklingsporn.vertx.jooq.generate.VertxGenerator.generateDao(VertxGenerator.java:479)
	at org.jooq.util.JavaGenerator.generateDao(JavaGenerator.java:2742)
	at org.jooq.util.JavaGenerator.generateDaos(JavaGenerator.java:2729)
	at io.github.jklingsporn.vertx.jooq.generate.VertxGenerator.generateDaos(VertxGenerator.java:231)
	at org.jooq.util.JavaGenerator.generate(JavaGenerator.java:459)
	at org.jooq.util.JavaGenerator.generate(JavaGenerator.java:405)
	at org.jooq.util.JavaGenerator.generate(JavaGenerator.java:327)
	at org.jooq.util.GenerationTool.run(GenerationTool.java:647)
	at org.jooq.util.GenerationTool.generate(GenerationTool.java:203)

Upon further debugging, it appears that the code is expecting fully qualified class name (at VertxGeneratorBuilder, lines 377-378) where as the actual value is just the class name i.e. without the package name. The custom code generator strategy is as is from the 3.0 version and worked fine. So something is going wrong in the 4.0-beta version. Could it be that the entire code base expects the string "pojos" but the package names that is provided by the custom code generator strategy is "pojo"? As an experiment, I did try to switch to "pojos" in the custom code but that didn't help.

CodeGeneratorStrategy.zip

Inconsistent behavior of from/toJson-methods when dealing with JsonObject or JsonArray

Looking at the following methods from a generated POJO

default ISomething fromJson(io.vertx.core.json.JsonObject json) {
        setSomeid(json.getInteger("someid"));
        setSomestring(json.getString("somestring"));
        setSomehugenumber(json.getLong("somehugenumber"));
        setSomesmallnumber(json.getInteger("somesmallnumber")==null?null:json.getInteger("somesmallnumber").shortValue());
        setSomeregularnumber(json.getInteger("someregularnumber"));
        setSomeboolean(json.getBoolean("someboolean"));
        setSomedouble(json.getDouble("somedouble"));
        setSomejsonobject(new io.github.jklingsporn.vertx.jooq.shared.JsonObjectConverter().from(json.getString("somejsonobject")));
        setSomejsonarray(new io.github.jklingsporn.vertx.jooq.shared.JsonArrayConverter().from(json.getString("somejsonarray")));
        return this;
    }


    default io.vertx.core.json.JsonObject toJson() {
        io.vertx.core.json.JsonObject json = new io.vertx.core.json.JsonObject();
        json.put("someid",getSomeid());
        json.put("somestring",getSomestring());
        json.put("somehugenumber",getSomehugenumber());
        json.put("somesmallnumber",getSomesmallnumber());
        json.put("someregularnumber",getSomeregularnumber());
        json.put("someboolean",getSomeboolean());
        json.put("somedouble",getSomedouble());
        json.put("somejsonobject",getSomejsonobject());
        json.put("somejsonarray",getSomejsonarray());
        return json;
    }

In this case, the fields somejsonobject or somejsonarray are converted using the JsonObjectConverter or JsonArrayConverter. That is done on a jOOQ-level. There is no need to convert them again in the fromJson-method (actually that fails with a ClassCastException).

Error converting binary(16) to String using custom converter

Hello,

Thanks for making this awesome project for vertx.
I'm currently using vertx-jooq-completablefuture-async and vertx-mysql-postgresql-client to talk to mysql 5.7
I wanted to use UUID in binary(16) form as primary key, so I wrote a simple custom converter as following:

public class UUIDConverter implements Converter<byte[], String> {

	private static final long serialVersionUID = 5799037733019312285L;

	@Override
    public String from(byte[] databaseObject) {
        return databaseObject == null ? null : UUID.toStringId(databaseObject);
    }

    @Override
    public byte[] to(String userObject) {
        return userObject == null ? null : UUID.toBinaryId(userObject);
    }

    @Override
    public Class<byte[]> fromType() {
        return byte[].class;
    }

    @Override
    public Class<String> toType() {
        return String.class;
    }
}
public class UUID {
    public static byte[] toBinaryId(String strId) {
    	byte[] src = new byte[16];
    	byte[] uuidBytes = new byte[16];
		try {
			src = Hex.decodeHex(strId.replaceAll("-", ""));
	    	ByteBuffer.wrap(uuidBytes)
				.put(src, 6, 2)
				.put(src, 4, 2)
				.put(src, 0, 4)
				.put(src, 8, 8);
		} catch (DecoderException e) {
			e.printStackTrace();
		}
    	return uuidBytes;
    }
    
    public static String toStringId(byte[] binId) {
    	byte[] uuidBytes = new byte[16];
    	String result = null;
    	ByteBuffer.wrap(uuidBytes)
			.put(binId, 4, 4)
			.put(binId, 2, 2)
			.put(binId, 0, 2)
			.put(binId, 8, 8);
		result = Hex.encodeHexString(uuidBytes);
    	return result;
    }
}

However I got this class casting error when trying to retrieve data from database.

2018-05-09T09:23:50,717 WARN  graphql.execution.SimpleDataFetcherExceptionHandler:23 - Exception while fetching data (/login) : java.lang.ClassCastException: java.lang.String cannot be cast to [B
java.util.concurrent.CompletionException: java.lang.ClassCastException: java.lang.String cannot be cast to [B
	at java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:273) ~[?:1.8.0_66]
	at java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:280) ~[?:1.8.0_66]
	at java.util.concurrent.CompletableFuture.uniApply(CompletableFuture.java:604) ~[?:1.8.0_66]
	at java.util.concurrent.CompletableFuture$UniApply.tryFire(CompletableFuture.java:577) ~[?:1.8.0_66]
	at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:474) ~[?:1.8.0_66]
	at java.util.concurrent.CompletableFuture.complete(CompletableFuture.java:1962) ~[?:1.8.0_66]
	at me.escoffier.vertx.completablefuture.VertxCompletableFuture.lambda$new$2(VertxCompletableFuture.java:70) ~[vertx-completable-future-0.1.1.jar:?]
	at java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:760) ~[?:1.8.0_66]
	at java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:736) ~[?:1.8.0_66]
	at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:474) ~[?:1.8.0_66]
	at java.util.concurrent.CompletableFuture.complete(CompletableFuture.java:1962) ~[?:1.8.0_66]
	at io.github.jklingsporn.vertx.jooq.completablefuture.async.AsyncCompletableFutureGenericQueryExecutor.lambda$executeAndClose$1(AsyncCompletableFutureGenericQueryExecutor.java:56) ~[vertx-jooq-completablefuture-async-4.0.0-BETA.jar:?]
	at io.vertx.ext.asyncsql.impl.AsyncSQLConnectionImpl.lambda$handleAsyncQueryResultToResultSet$12(AsyncSQLConnectionImpl.java:306) ~[vertx-mysql-postgresql-client-3.5.1.jar:3.5.1]
	at io.vertx.ext.asyncsql.impl.ScalaUtils$3.apply(ScalaUtils.java:91) ~[vertx-mysql-postgresql-client-3.5.1.jar:3.5.1]
	at io.vertx.ext.asyncsql.impl.ScalaUtils$3.apply(ScalaUtils.java:87) ~[vertx-mysql-postgresql-client-3.5.1.jar:3.5.1]
	at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:60) ~[scala-library-2.12.4.jar:?]
	at io.vertx.ext.asyncsql.impl.VertxEventLoopExecutionContext.lambda$execute$0(VertxEventLoopExecutionContext.java:59) ~[vertx-mysql-postgresql-client-3.5.1.jar:3.5.1]
	at io.vertx.core.impl.ContextImpl.lambda$wrapTask$2(ContextImpl.java:339) ~[vertx-core-3.5.1.jar:3.5.1]
	at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163) [netty-common-4.1.19.Final.jar:4.1.19.Final]
	at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:404) [netty-common-4.1.19.Final.jar:4.1.19.Final]
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:463) [netty-transport-4.1.19.Final.jar:4.1.19.Final]
	at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:886) [netty-common-4.1.19.Final.jar:4.1.19.Final]
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) [netty-common-4.1.19.Final.jar:4.1.19.Final]
	at java.lang.Thread.run(Thread.java:745) [?:1.8.0_66]
Caused by: java.lang.ClassCastException: java.lang.String cannot be cast to [B
	at com.ark.jooq.generate.UUIDConverter.from(UUIDConverter.java:9) ~[jooq-generate-1.0.jar:?]
	at io.github.jklingsporn.vertx.jooq.shared.async.AbstractAsyncQueryExecutor.lambda$convertFromSQL$2(AbstractAsyncQueryExecutor.java:55) ~[vertx-jooq-shared-async-4.0.0-BETA.jar:?]
	at java.util.function.Function.lambda$andThen$6(Function.java:88) ~[?:1.8.0_66]
	at io.github.jklingsporn.vertx.jooq.completablefuture.async.AsyncCompletableFutureQueryExecutor.lambda$findOne$1(AsyncCompletableFutureQueryExecutor.java:43) ~[vertx-jooq-completablefuture-async-4.0.0-BETA.jar:?]
	at java.util.concurrent.CompletableFuture.uniApply(CompletableFuture.java:602) ~[?:1.8.0_66]
	... 21 more
2018-05-09T09:23:50,767 WARN  com.ark.server.LoggerHandlerImpl:162 - 0:0:0:0:0:0:0:1 -- "POST /graphql" 400 8871 154ms "http://localhost:8080/?query=mutation%20%7B%0A%20%20login(input%3A%20%7B%0A%20%20%20%20email%3A%20%22andy%22%2C%0A%20%20%20%20password%3A%20%22hope%20is%20a%20good%20thing%22%2C%0A%20%20%7D)%20%7B%0A%20%20%20%20userId%0A%20%20%20%20name%0A%20%20%20%20lastLogin%0A%20%20%20%20faceUrl%0A%20%20%20%20session%0A%20%20%20%20roles%0A%20%20%20%20createTime%0A%20%20%20%20updateTime%0A%20%20%7D%0A%7D" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36"
	{"query":"mutation {\n  login(input: {\n    email: \"andy\",\n    password: \"hope is a good thing\",\n  }) {\n    userId\n    name\n    lastLogin\n    faceUrl\n    session\n    roles\n    createTime\n    updateTime\n  }\n}","variables":null}

With a little debuging, I found out that the result from the data are Base64 encoded strings instead of byte[] the converter expects.
Could you help me with this issue?

Thank you!

Unrecognized types: UUID, LocalDate, smallint etc.

I'm using the 4.0-beta version and am getting a bunch of these warnings:

[INFO] Generating POJO          : Address.java
[WARNING] Omitting unrecognized type java.util.UUID for column customerId in table Address!
[WARNING] Omitting unrecognized type java.time.LocalDate for column birthDate in table Child!
	
[INFO] Generate RowMappers ...  
[WARNING] Omitting unrecognized type DataType [ t=smallint; p=16; s=0; u="pg_catalog"."int2"; j=null ] (java.lang.Short) for column countryId in table Address!

To partially workaround the POJO warnings, I wrote a custom CodeGenerator that extends RXReactiveVertxGenerator to handle the custom types - This is same as what I'd in 3.0 version. So two questions:

  1. Aren't these types supposed to be handled (in 4.0 version) by the generator given that the default jooq generator handles it? Further, I see that these types are also supported by the reactive-pg-client.

  2. What workaround do I need to implement about the smallint datatype warning when the RowMappers are generated?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.