Giter Club home page Giter Club logo

vertx-service-proxy's Introduction

Service Proxies

Build Status (5.x) Build Status (4.x)

Please see the main documentation on the web-site for a full description:

Many Vert.x applications include various services which do useful things and often can be reused from one application to another. An example would be a database service.

Usually those services run in their own verticle and interact with other verticles by receiving and sending messages, e.g.

// Assume database service is already deployed somewhere....

// Save some data in the database

JsonObject message = new JsonObject();
message.putString("collection", "mycollection");
message.putObject("document", new JsonObject().putString("name", "tim"));
DeliveryOptions options = new DeliveryOptions().addHeader("action", "save");
vertx.eventBus().send("database-service-address", message, options, res2 -> {
    if (res2.succeeded()) {
        // done
    }
}

When creating a service there's a certain amount of boiler-plate code to listen on the eventbus for incoming messages, route them to the appropriate method and return results on the event bus.

With Vert.x service proxies, you can avoid writing all that boiler-plate code and concentrate on writing your service.

You write your service as a Java interface and annotate it with the @ProxyGen annotation, for example:

@ProxyGen
public interface SomeDatabaseService {

    // A couple of factory methods to create an instance and a proxy

    static SomeDatabaseService create(Vertx vertx) {
       return new SomeDatabaseServiceImpl(vertx);
    }

    static SomeDatabaseService createProxy(Vertx vertx, String address) {
      return new SomeDatabaseServiceVertxEBProxy(vertx, address);
    }

    // Actual service operations here...

    void save(String collection, JsonObject document, Handler<AsyncResult<Void>> resultHandler);
}

Given the interface, Vert.x will generate all the boiler-plate required to access your service over the event bus, and it will also generate a client side proxy for your service, so your clients can use a rich idiomatic API for your service instead of having to manually craft event bus messages to send. The client side proxy will work irrespective of where your service actually lives on the event bus (potentially on a different machine).

That means you can interact with your service like this:

// Assume database service is already deployed somewhere....

// Create a proxy
SomeDatabaseService service = SomeDatabaseService.createProxy(vertx, "database-service-address");

// Save some data in the database - this time using the proxy
service.save("mycollection", new JsonObject().putString("name", "tim"), res2 -> {
    if (res2.succeeded()) {
        // done
    }
});

vertx-service-proxy's People

Contributors

adrianluisgonzalez avatar afloarea avatar bobbybakes avatar cescoffier avatar cvgaviao avatar dano avatar dependabot[bot] avatar gaol avatar infosec812 avatar mchunkytrunk avatar meggarr avatar msavy avatar nscavell avatar okou19900722 avatar plause avatar pmlopes avatar purplefox avatar roaring-cow avatar ruget avatar sdhays avatar shaunrader avatar slinkydeveloper avatar tsegismont avatar vietj avatar vorimo avatar yeikel 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

Watchers

 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

vertx-service-proxy's Issues

vertx-codegen dependency

To define a service proxy, you need to use the ProxyGen annotation, which is actually in the vertx-codegen package which is not included as a dependency when you include the vertx-service-proxy package in your dependency. The documentation should at least clearly specify that you need to add in the vertx-codegen package to get the ProxyGen annotation; otherwise it's really not clear.

Gradle tests are not executed when adding compile "io.vertx:vertx-service-proxy:3.5.3:processor" to dependencies

When following the documentation https://vertx.io/docs/vertx-service-proxy/java/#_code_generation and adding compile "io.vertx:vertx-service-proxy:3.5.3:processor" to the dependencies the tests are skipped.

Gradle Log:

:clean
warning: No SupportedSourceVersion annotation found on io.vertx.serviceproxy.ServiceProxyProcessor, returning RELEASE_6.
warning: Supported source version 'RELEASE_6' from annotation processor 'io.vertx.serviceproxy.ServiceProxyProcessor' less than -source '1.8'
2 warnings
:compileJava
:processResources NO-SOURCE
:classes
:compileTestJava
:processTestResources NO-SOURCE
:testClasses
:test
:test NO-SOURCE
Deprecated Gradle features were used in this build, making it incompatible with Gradle 5.0.
See https://docs.gradle.org/4.6/userguide/command_line_interface.html#sec:command_line_warnings
BUILD SUCCESSFUL in 1s
3 actionable tasks: 3 executed
16:29:37: Tasks execution finished 'clean test'.

Reproduction:

  1. clone the repo https://github.com/Nols1000/vertx_codegen_processor_test
  2. run gradle clean test

Allow for generating TypeScript service proxies for Angular

Example TypeScript implementation:

declare type HandlerType = (err: any, result: any) => any;

class AmbassadorsService {

  private closed = false;

  // There's some ambiguity here around what are the right params....
  // See: https://github.com/vert-x3/vertx-lang-js/issues/67
  public static create(vertx: any, address: string): void {
    vertx.send(address,
      {'vertx': vertx},
      {'action': 'create'},
      (err, result) =>
        handler(err, result && new AmbassadorsService(vertx, result.headers.proxyaddr)));
  }

  public static createProxy(vertx: any, handler: HandlerType,
    eb: any, address: string, ebAddress: string): void {
    eb.send(address,
      {'vertx': vertx,
      'ebAddress': ebAddress},
      {'action': 'createProxy'});
  };

  constructor(private j_eb: any, private j_address: string) {
  }

  // TODO: do we need this?!?!?
  private convCharCollection(coll: any) {
    const ret = [];
      for (let i = 0; i < coll.length; i++) {
        ret.push(String.fromCharCode(coll[i]));
      }
      return ret;
  }

  public createOne(data: any, handler: HandlerType): AmbassadorsService {
    if (data === null || data === undefined) {
      throw new TypeError('function invoked with invalid arguments');
    }
    this.checkNotClosed();
    this.j_eb.send(this.j_address,
      {'data': data},
      {'action': 'createOne'},
      (err, result) => handler(err, result && result.body));
    return this;
  }

  public delete(id: string, handler: HandlerType): AmbassadorsService {
    if (id === null || id === undefined) {
      throw new TypeError('function invoked with invalid arguments');
    }
    this.checkNotClosed();
    this.j_eb.send(this.j_address,
      {'id' : id},
      {'action': 'delete'},
      (err, result) => handler(err, result && result.body));
    return this;
  }

  public getAll(handler: HandlerType): AmbassadorsService {
    this.checkNotClosed();
    this.j_eb.send(this.j_address,
      {},
      {'action': 'getAll'},
      (err, result) => handler(err, result && result.body));
    return this;
  }

  public getById(id: string, handler: HandlerType): AmbassadorsService {
    if (id === null || id === undefined) {
      throw new TypeError('function invoked with invalid arguments');
    }
    this.checkNotClosed();
    this.j_eb.send(this.j_address,
      {'id': id},
      {'action': 'getById'},
      (err, result) => handler(err, result && result.body));
    return this;
  }

  public commands(command: any, handler: HandlerType): AmbassadorsService {
    if (command === null || command === undefined) {
      throw new TypeError('function invoked with invalid arguments');
    }
    this.checkNotClosed();
    this.j_eb.send(this.j_address,
      {'command': command},
      {'action': 'commands'},
      (err, result) => handler(err, result && result.body));
    return this;
  }

  public close(): void {
    this.checkNotClosed();
    this.j_eb.send(this.j_address, {}, {'action': 'close'});
    closed = true;
  }

  private checkNotClosed() {
    if (this.closed) {
      throw new Error('Proxy is closed');
    }
  }
}

UUID incoming/return parameters + Collection/List/Set/Stream<MyType> support ??

Hi vertx folks,
I would like to ask question related to Service Proxy java code generation. Gradle 4.3.1 is used.

1. How can I use UUID as part of ServiceProxy generation? (we use java UUID and Cassandra datastax driver time-based UUID classes)
2. Are Collection/List/Set/Stream with custom type supported as incoming and return parameters?

I'm trying to use example from here as reference:
https://github.com/advantageous/vertx-node-ec2-eventbus-example/wiki/Step-5-Using-Vertx-Service-Proxies

e.g. I have DTO as:

@DataObject
public class MyEntityDTO {
  private UUID myEntityId;
....
  public MyEntityDTO(JsonObject data) {....}
}

Service Proxy Interface like:

@ProxyGen
@VertxGen
public interface MyEntityServiceAsynch {
void save(MyEntityDTO entity, Handler<AsyncResult<UUID>> resultHandler);
void retrieveByExample(MyEntityDTO entityQueryByExample, Handler<AsyncResult<List<MyEntityDTO>>> resultHandler);
....}

I have 'package-info.java' files in folders, but don't understand how can I generate UUIDs as part of Service contract ? Can someone give a hint?


Could not generate model for .....service.MyEntityServiceAsynch#save(.....dto.MyEntityDTO,io.vertx.core.Handler<io.vertx.core.AsyncResult<java.util.UUID>>): type io.vertx.core.Handler<io.vertx.core.AsyncResult<java.util.UUID>> is not legal for use for a parameter in code generation
  void save(MyEntityDTO entity, final Handler<AsyncResult<UUID>> resultHandler);
       ^
warning: The following options were not recognized by any processor: '[outputDirectory]'

I'm appreciate for any hint.

Support Type Variable in Interface

I'd like to do something similar to what I can do with Spring Data, where I can declare an interface with generics and then extend that interface with the appropriate type information and vert.x service proxies has the smarts to generate the appropriate information behind the scenes

For example, I'd like to use the following code without rewriting the same interface for every repository, which I anticipate to have several:

public interface Repository<T extends Aggregate> {
    void load(String aggregateIdentifier, Handler<AsyncResult<T>> resultHandler);

    void save(T aggregate, Handler<AsyncResult<Void>> resultHandler);
}

@ProxyGen
public interface DriverRepository extends Repository<Driver> {
}

public interface Aggregate {
    String identifier();
}


@DataObject(generateConverter = true)
public class Driver implements Aggregate {

    private String id;

    public Driver(JsonObject jsonObject) {
    }

    public Driver(String id) {
        this.id = id;
    }

    protected Driver() {
    }

    @Override
    public String identifier() {
        return id;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public JsonObject toJson() {
        JsonObject json = new JsonObject();
        return json;
    }
}

Be able to use a Enum type as a result

Documentation says that an Enum can be passed as a parameter to a method but not for a result.

I tried an got a IllegalArgumentException:

No message codec for type: class com.example.MyEnum

Any chance we can change that? Or there is a technical reason behind this choice ?

I'm running Vert.x 3.1.

Thanks!

Missing @Override annotation on methods in *VertxEBProxy

In recent version of IntelliJ IDEA this warning is indicated also on the service interface annotated with @ProxyGen, which adds unnecessary "noise" to the code. Please generate @Override annotation on *VertxEBProxy methods.

On generated service proxy, Error - unreported exception java.io.UnsupportedEncodingException; must be caught or declared to be thrown

Compilation failure with release 3.5.1
On generated service proxy, Error - unreported exception java.io.UnsupportedEncodingException; must be caught or declared to be thrown

generate proxy code -

public void handle(Message msg) {
try {
...
}
catch (Throwable t) {
msg.reply(new ServiceException(500, t.getMessage()));
throw t;
}
}

Stacktrace -
UserAsyncServiceVertxProxyHandler.java:[339,7] unreported exception java.io.UnsupportedEncodingException; must be caught or declared to be thrown

    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:212)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:116)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:80)
    at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:51)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
    at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:307)
    at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:193)
    at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:106)
    at org.apache.maven.cli.MavenCli.execute(MavenCli.java:863)
    at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:288)
    at org.apache.maven.cli.MavenCli.main(MavenCli.java:199)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)

Caused by: org.apache.maven.plugin.compiler.CompilationFailureException: Compilation failure
/Users/admin/Documents/Development/langAppServer/vertxweb/target/generated-sources/annotations/com/bijay/langapp/web/verticles/user/UserAsyncServiceVertxProxyHandler.java:[339,7] unreported exception java.io.UnsupportedEncodingException; must be caught or declared to be thrown

    at org.apache.maven.plugin.compiler.AbstractCompilerMojo.execute(AbstractCompilerMojo.java:858)
    at org.apache.maven.plugin.compiler.CompilerMojo.execute(CompilerMojo.java:129)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:134)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:207)

nulls not handled correctly in generated VertxProxyHandler

I have an API roughly corresponding to:

void getResult(String key1, String key2, Handler<AsyncResult<Result>> handler);
void getBulkResults(List<JsonArray> lookup, Handler<AsyncResult<List<Result>>> handler);

The first function results in generated code that handles null values:

msg.reply(res.result() == null ? null : res.result().toJson());

But the generated code for the second function assumes all elements in the list are non-null:

msg.reply(new JsonArray(res.result().stream().map(Result::toJson).collect(Collectors.toList())));

Ideally there'd be consistency in the generated code. In this case return nulls inside the list (and serialize as [ ..., null, ... ]

Gradle 5.0 doc update

From Gradle 5.0 people must use annotationProcessor to add dependencies as annotation processor. Gradle creates a classpath only for it:

Since implementation details matter for annotation processors, they must be declared separately on the annotation processor path. Gradle ignores annotation processors on the compile classpath.

Major regressions between 3.5 and 3.6

While upgrading code from 3.5.x to 3.6 (the guide for Java developers), I encountered 2 regressions.

Need for @VertxGen

We now need to also add @VertxGen.

Before:

@ProxyGen
public interface WikiDatabaseService { ... }

After:

@ProxyGen
@VertxGen
public interface WikiDatabaseService { ... }

Otherwise, compilation fails.

Static methods aren't being ignored anymore

Code generation used to ignore static methods, such as the idiomatic create methods we have in services:

  static WikiDatabaseService create(JDBCClient dbClient, HashMap<SqlQuery, String> sqlQueries, Handler<AsyncResult<WikiDatabaseService>> readyHandler) {
    return new WikiDatabaseServiceImpl(dbClient, sqlQueries, readyHandler);
  }

  static WikiDatabaseService createProxy(Vertx vertx, String address) {
    return new WikiDatabaseServiceVertxEBProxy(vertx, address);
  }

We now need to explicitly ignore them otherwise compilation fails:

  @GenIgnore
  static WikiDatabaseService create(JDBCClient dbClient, HashMap<SqlQuery, String> sqlQueries, Handler<AsyncResult<WikiDatabaseService>> readyHandler) {
    return new WikiDatabaseServiceImpl(dbClient, sqlQueries, readyHandler);
  }

  @GenIgnore
  static WikiDatabaseService createProxy(Vertx vertx, String address) {
    return new WikiDatabaseServiceVertxEBProxy(vertx, address);
  }

Allow pluggable marshallers

Generated proxies currently always encode/decode the request/response to/from JSON.

This is nice and interoperable and allows services to be easily called by just sending messages directly on the event bus, but it is not necessarily very efficient.

We should abstract out the marshalling code and allow it to be pluggable. So that, for example an efficient binary encoding can be used (or whatever), if the user prefers that.

allow access to headers

Allow writing and reading headers for EventBusService.

E.g.:

EventBusService.getProxy(discovery, SomeService) { AsyncResult<SomeService> ar1 ->
    SomeService someService = ar1.result()
    // here, it will be nice to have an option to allow *sending* some headers along the "someCommand"
    someService.someMethod(someCommand) { AsyncResult<SomeResult> ar2 ->
        // do something
    }
}

interface SomeService {
    // here, it will be nice to have an option to allow *reading* headers along the "someCommand"
    void someMethod(SomeCommand someCommand, Handler<AsyncResult<SomeResult>> handler) {
        // do something
    }
}

@ProxyGen buildable on 3.0.0 fails on 3.1.0-SNAPSHOT with 'cannot be cast to io.vertx.codegen.TypeInfo$Class$Api'

An interface that looks (simplified) like this, and compiled fine with vertx 3.0.0:

IngestorToPolicyService is labelled with @ProxyGen and @VertxGen.

@ProxyGen
public interface InitializeIngestorService {

    void createIngestor(String uuid, Handler<AsyncResult<IngestorToPolicyService>> resultHandler);

    static InitializeIngestorService create(Vertx vertx) {
        return new InitializeIngestorServiceImpl(vertx);
    }

    static InitializeIngestorService createProxy(Vertx vertx, String address) {
        return ProxyHelper.createProxy(InitializeIngestorService.class, vertx, address);
    }
}

The error is extremely cryptic to me:

SEVERE: Could not generate element for io.vertx.apiman.gateway.platforms.vertx2.services.InitializeIngestorService: io.vertx.codegen.TypeInfo$Class cannot be cast to io.vertx.codegen.TypeInfo$Class$Api
java.lang.ClassCastException: io.vertx.codegen.TypeInfo$Class cannot be cast to io.vertx.codegen.TypeInfo$Class$Api
    at io.vertx.codegen.ClassModel.getTypeParams(ClassModel.java:215)
    at io.vertx.codegen.ClassModel.getVars(ClassModel.java:807)
    at io.vertx.codegen.CodeGenProcessor.lambda$process$66(CodeGenProcessor.java:148)
    at io.vertx.codegen.CodeGenProcessor$$Lambda$23/895697353.accept(Unknown Source)
    at java.util.stream.StreamSpliterators$WrappingSpliterator$$Lambda$24/678054994.accept(Unknown Source)
    at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
    at java.util.HashMap$EntrySpliterator.forEachRemaining(HashMap.java:1683)
    at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:512)
    at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:502)
    at java.util.stream.StreamSpliterators$WrappingSpliterator.forEachRemaining(StreamSpliterators.java:312)
    at java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:743)
    at java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:743)
    at java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:743)
    at java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:743)
    at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580)
    at io.vertx.codegen.CodeGenProcessor.process(CodeGenProcessor.java:137)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:794)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:705)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment.access$1800(JavacProcessingEnvironment.java:91)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1035)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1176)
    at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1170)
    at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:856)
    at com.sun.tools.javac.main.Main.compile(Main.java:523)
    at com.sun.tools.javac.api.JavacTaskImpl.doCall(JavacTaskImpl.java:129)
    at com.sun.tools.javac.api.JavacTaskImpl.call(JavacTaskImpl.java:138)
    at org.codehaus.plexus.compiler.javac.JavaxToolsCompiler.compileInProcess(JavaxToolsCompiler.java:126)
    at org.codehaus.plexus.compiler.javac.JavacCompiler.performCompile(JavacCompiler.java:169)
    at org.apache.maven.plugin.compiler.AbstractCompilerMojo.execute(AbstractCompilerMojo.java:785)
    at org.apache.maven.plugin.compiler.CompilerMojo.execute(CompilerMojo.java:129)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:134)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:208)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:116)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:80)
    at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:51)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
    at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:307)
    at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:193)
    at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:106)
    at org.apache.maven.cli.MavenCli.execute(MavenCli.java:862)
    at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:286)
    at org.apache.maven.cli.MavenCli.main(MavenCli.java:197)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)

Switching to 3.5 - Could not find proxy get templ

By switching to 3.5 from 3.4.2 on build, when it comes to god generation:

for the

@VertxGen
@ProxyGen
public interface MyService {

Could not generate model for com.my.MyService ...

Could not load template /vertx-js/template/common.templ from template jar:file:/../.m2/repository/io/vertx/vertx-sockjs-service-proxy/3.5.0/vertx-sockjs-service-proxy-3.5.0.jar!/vertx-sockjs-service-proxy/template/proxygen.templ

Was it dramatically modified ? no explanation why it can not load it.

--

org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.6.0:compile (default-compile) on project my-api: Compilation failure
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:212)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:116)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:80)
at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:51)
at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:307)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:193)
at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:106)
at org.apache.maven.cli.MavenCli.execute(MavenCli.java:863)
at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:288)
at org.apache.maven.cli.MavenCli.main(MavenCli.java:199)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)
Caused by: org.apache.maven.plugin.compiler.CompilationFailureException: Compilation failure
at org.apache.maven.plugin.compiler.AbstractCompilerMojo.execute(AbstractCompilerMojo.java:1029)
at org.apache.maven.plugin.compiler.CompilerMojo.execute(CompilerMojo.java:137)
at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:134)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:207)
... 20 more

Intermittent failure: ServiceProxyTest.testConnectionTimeout

Pile d'exécution

java.lang.AssertionError: null
	at org.junit.Assert.fail(Assert.java:86)
	at org.junit.Assert.assertTrue(Assert.java:41)
	at org.junit.Assert.assertTrue(Assert.java:52)
	at io.vertx.test.core.AsyncTestBase.assertTrue(AsyncTestBase.java:372)
	at io.vertx.serviceproxy.test.ServiceProxyTest.lambda$null$95(ServiceProxyTest.java:860)
Sortie d'erreur standard

Starting test: ServiceProxyTest#testConnectionTimeout 
java.lang.AssertionError
	at org.junit.Assert.fail(Assert.java:86)
	at org.junit.Assert.assertTrue(Assert.java:41)
	at org.junit.Assert.assertTrue(Assert.java:52)
	at io.vertx.test.core.AsyncTestBase.assertTrue(AsyncTestBase.java:372)
	at io.vertx.serviceproxy.test.ServiceProxyTest.lambda$null$95(ServiceProxyTest.java:860)
	at io.vertx.core.eventbus.impl.HandlerRegistration.deliver(HandlerRegistration.java:212)
	at io.vertx.core.eventbus.impl.HandlerRegistration.handle(HandlerRegistration.java:191)
	at io.vertx.core.eventbus.impl.EventBusImpl.lambda$deliverToHandler$3(EventBusImpl.java:524)
	at io.vertx.core.impl.ContextImpl.lambda$wrapTask$2(ContextImpl.java:337)
	at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163)
	at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:403)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:445)
	at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:858)
	at java.lang.Thread.run(Thread.java:745)
Unhandled exception 
java.lang.AssertionError
	at org.junit.Assert.fail(Assert.java:86)
	at org.junit.Assert.assertTrue(Assert.java:41)
	at org.junit.Assert.assertTrue(Assert.java:52)
	at io.vertx.test.core.AsyncTestBase.assertTrue(AsyncTestBase.java:372)
	at io.vertx.serviceproxy.test.ServiceProxyTest.lambda$null$95(ServiceProxyTest.java:860)
	at io.vertx.core.eventbus.impl.HandlerRegistration.deliver(HandlerRegistration.java:212)
	at io.vertx.core.eventbus.impl.HandlerRegistration.handle(HandlerRegistration.java:191)
	at io.vertx.core.eventbus.impl.EventBusImpl.lambda$deliverToHandler$3(EventBusImpl.java:524)
	at io.vertx.core.impl.ContextImpl.lambda$wrapTask$2(ContextImpl.java:337)
	at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163)
	at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:403)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:445)
	at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:858)
	at java.lang.Thread.run(Thread.java:745)

https://vertx.ci.cloudbees.com/job/vert.x3-service-proxy/2720
https://vertx.ci.cloudbees.com/job/vert.x3-service-proxy/2711
https://vertx.ci.cloudbees.com/job/vert.x3-service-proxy/2709

Service proxies with pub-sub semantics

I have a use-case where I'm doing a pub-sub actions instead of 1:N send; it'd be great to have a similar style service-proxy setup. Presently I'm just doing it the traditional way with hand-built proxy and service.

Is something that would validly come under this project, or perhaps requires a separate one? it's semantics would certainly be different with respect to error and reply handling.

Updating to 3.4.2 generates error

Hi everybody, when I moved from vertx 3.4.1 to 3.4.2, proxygen fails with error.

PS: clean classes and other stuff not helped

ProxyDealSpread annotated with @DataObject and has contructor
@SuppressWarnings("unused") public ProxyDealSpread(JsonObject obj) {...}

Could not generate element for com.novice.proxyapi.transport.object.ProxyDealSpread: null java.lang.UnsupportedOperationException at java.util.AbstractCollection.add(AbstractCollection.java:262) at io.vertx.codegen.DataObjectModel.lambda$processMethods$7(DataObjectModel.java:324) at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184) at java.util.Iterator.forEachRemaining(Iterator.java:116) at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801) at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580) at java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:270) at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175) at java.util.Iterator.forEachRemaining(Iterator.java:116) at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801) at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481) at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151) at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174) at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418) at io.vertx.codegen.DataObjectModel.processMethods(DataObjectModel.java:324) at io.vertx.codegen.DataObjectModel.traverse(DataObjectModel.java:217) at io.vertx.codegen.DataObjectModel.process(DataObjectModel.java:154) at io.vertx.codegen.CodeGen.getDataObjectModel(CodeGen.java:184) at io.vertx.codegen.CodeGen.lambda$null$15(CodeGen.java:112) at io.vertx.codegen.CodeGen$ModelEntry.getValue(CodeGen.java:218) at io.vertx.codegen.CodeGen$ModelEntry.getValue(CodeGen.java:200) at io.vertx.codegen.CodeGenProcessor.lambda$process$5(CodeGenProcessor.java:204) at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) at java.util.HashMap$EntrySpliterator.forEachRemaining(HashMap.java:1691) at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481) at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) at java.util.stream.StreamSpliterators$WrappingSpliterator.forEachRemaining(StreamSpliterators.java:312) at java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:742) at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580) at io.vertx.codegen.CodeGenProcessor.process(CodeGenProcessor.java:202) at com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:794) at com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:705) at com.sun.tools.javac.processing.JavacProcessingEnvironment.access$1800(JavacProcessingEnvironment.java:91) at com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1035) at com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1176) at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1170) at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:856) at com.sun.tools.javac.main.Main.compile(Main.java:523) at com.sun.tools.javac.api.JavacTaskImpl.doCall(JavacTaskImpl.java:129) at com.sun.tools.javac.api.JavacTaskImpl.call(JavacTaskImpl.java:138) at org.gradle.api.internal.tasks.compile.JdkJavaCompiler.execute(JdkJavaCompiler.java:46) at org.gradle.api.internal.tasks.compile.JdkJavaCompiler.execute(JdkJavaCompiler.java:33) at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.delegateAndHandleErrors(NormalizingJavaCompiler.java:104) at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.execute(NormalizingJavaCompiler.java:53) at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.execute(NormalizingJavaCompiler.java:38) at org.gradle.api.internal.tasks.compile.CleaningJavaCompilerSupport.execute(CleaningJavaCompilerSupport.java:35) at org.gradle.api.internal.tasks.compile.CleaningJavaCompilerSupport.execute(CleaningJavaCompilerSupport.java:25) at org.gradle.api.tasks.compile.JavaCompile.performCompilation(JavaCompile.java:206) at org.gradle.api.tasks.compile.JavaCompile.compile(JavaCompile.java:187)

Reply with an exception without losing stack trace

I'm using generated VertxProxyHandler class for my service (SomeServiceVertxProxyHandler. class).
When delivering a message through an event bus (in the case that an exception occurred during the execution), I get another exception that wraps my real one and thus losing the stacktrace.
The main problem is in this code:

 public void handle(Message<JsonObject> msg) {
    try{
      JsonObject json = msg.body();
      String action = msg.headers().get("action");
      if (action == null) throw new IllegalStateException("action not specified");
      accessed();
      switch (action) {
        case "getStart": {
          service.getStart((java.lang.String)json.getValue("tmsec"),
                        HelperUtils.createListHandler(msg));
          break;
        }
...

Look at the HelperUtils.createListHandler(msg) method:

public static <T> Handler<AsyncResult<List<T>>> createListHandler(Message msg) {
    return res -> {
      if (res.failed()) {
        if (res.cause() instanceof ServiceException) {
          msg.reply(res.cause());
        } else {
          msg.reply(new ServiceException(-1, res.cause().getMessage()));
        }

If res.cause() instance of Exception (any kind of exception that may happens) and not contains message of the cause (as in case when you pass null in Objects.requireNonNull()) you will get completely another stacktrace with completely not informative message.

May be it will be better to call initCause(Throwable t) or addSuppressed(Throwable t) to not losing original exception?

Migrate the sockjs service proxies to vertx-web

Because it creates a cycle in the build, we should move the SockJS client generation to vert.x web (alongside the sockjs bridge implementation).

This introduces a breaking change, as users would need to add another dependency to get the client generated.

when will it invoke

private static <T> Map<String, T> convertMap(Map map) {
    if (map.isEmpty()) { 
      return (Map<String, T>) map; 
    } 
    Object elem = map.values().stream().findFirst().get(); 
    if (!(elem instanceof Map) && !(elem instanceof List)) { 
      return (Map<String, T>) map; 
    } else { 
      Function<Object, T> converter; 
      if (elem instanceof List) { 
        converter = object -> (T) new JsonArray((List) object); 
      } else { 
        converter = object -> (T) new JsonObject((Map) object); 
      } 
      return ((Map<String, T>) map).entrySet() 
       .stream() 
       .collect(Collectors.toMap(Map.Entry::getKey, converter::apply)); 
    } 
  }

this method in "proxygen.templ"
but service method param Map only support Json or basic value,when will the converter invoker

sorry for bad english!I'm Chinese,Thank you

proxyClass is reall not require?

: Unhandled exception
java.lang.IllegalStateException: Cannot find proxyClass: com.miaozhen.vertx.cluster.consumer.HelloServiceVertxProxyHandler
at io.vertx.serviceproxy.ProxyHelper.loadClass(ProxyHelper.java:104)
at io.vertx.serviceproxy.ProxyHelper.registerService(ProxyHelper.java:78)
at io.vertx.serviceproxy.ProxyHelper.registerService(ProxyHelper.java:71)
at io.vertx.serviceproxy.ProxyHelper.registerService(ProxyHelper.java:65)
at com.miaozhen.vertx.cluster.consumer.ServiceVerticle.lambda$0(ServiceVerticle.java:58)
at io.vertx.core.impl.VertxImpl.lambda$createAndStartEventBus$267(VertxImpl.java:177)
at io.vertx.core.eventbus.impl.clustered.ClusteredEventBus.lambda$null$125(ClusteredEventBus.java:94)
at io.vertx.core.net.impl.NetServerImpl.lambda$null$32(NetServerImpl.java:252)
at io.vertx.core.impl.ContextImpl.lambda$wrapTask$16(ContextImpl.java:335)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:358)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:357)
at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:112)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ClassNotFoundException: com.miaozhen.vertx.cluster.consumer.HelloServiceVertxProxyHandler
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at io.vertx.serviceproxy.ProxyHelper.loadClass(ProxyHelper.java:102)
... 12 more

Generated Service and Proxy code doesn't compile if interface doesn't import java.util.List

When generating code using the @ProxyGen annotation, if the java.util.List class is not used by any of the methods in the interface, the generated classes will not have an import for java.util.List making them not compile.

From an inspection of the generated code, it looks like the unresolved imports are coming from unused private methods, and if they are deleted, then the generated source seems to work.

Interface and Service in groovy

Is there a sample on how to define the interface and the service in Groovy?

Consuming from groovy seemss quite easy, but I haven't been able to define the interface and the implementeation in Groovy.
Even just the implementation seems hard to achieve. Is that actually an option? an if so, does anyone has a pointer on how to do it ?

Kind regards

VertxProxyHandler fails when replying with DataObject

Generated VertxProxyHandler and VertxEBProxy do not require MessageCodecs for DataObjects that are passed as inputs. However sending a DataObject reply produces the following error: java.lang.IllegalArgumentException: No message codec for type.

This is because inputs are serialized/unserialized from Json while the reply is sent untouched through the event bus.

In a sense MessageCodec behaviour is backed in the VertxEBProxy and VertxProxyHandler for input and not outputs.

This is inconsistent and seems to me like a bug. This does not match what is documented here http://vertx.io/docs/vertx-service-proxy/java/#_restrictions_for_service_interface, which states that a DataObject should be ok for input as well as reply.

Annotation processor 'io.vertx.codegen.CodeGenProcessor' not found

Hi! While compiling my Vertx project using vertx-service-proxy, I found I get an confusing error: Annotation processor 'io.vertx.codegen.CodeGenProcessor' not found

Here is the pom.xml (Or you can get the whole project here: https://github.com/CasterKKK/CasterMovieVertx if you want):

<dependencies>
    ...
    <dependency>
        <groupId>io.vertx</groupId>
        <artifactId>vertx-service-proxy</artifactId>
        <classifier>processor</classifier>
    </dependency>
    ...
</dependencies>

...
<plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>${maven-compiler.version}</version>
        <configuration>
            <source>${java.version}</source>
            <target>${java.version}</target>
            <useIncrementalCompilation>false</useIncrementalCompilation>
            <encoding>${project.build.sourceEncoding}</encoding>
            <generatedSourcesDirectory>src/main/generated</generatedSourcesDirectory>
            <generatedTestSourcesDirectory>src/test/generated</generatedTestSourcesDirectory>
         </configuration>
           <executions>
                <execution>
                    <id>default-compile</id>
                        <configuration>
                            <annotationProcessors>
                                <annotationProcessor>io.vertx.codegen.CodeGenProcessor</annotationProcessor>
                            </annotationProcessors>
                            <generatedSourcesDirectory>src/main/generated</generatedSourcesDirectory>
                            <compilerArgs>
                                <arg>-Acodegen.output=${project.basedir}/src/main</arg>
                            </compilerArgs>
                        </configuration>
                    </execution>
                    <execution>
                        <id>default-testCompile</id>
                        <configuration>
                            <annotationProcessors>
                                <annotationProcessor>io.vertx.codegen.CodeGenProcessor</annotationProcessor>
                            </annotationProcessors>
                           <generatedTestSourcesDirectory>src/test/generated</generatedTestSourcesDirectory>
                       <compilerArgs>
                          <arg>-Acodegen.output=${project.basedir}/src/test</arg>
                    </compilerArgs>
                </configuration>
             </execution>
         </executions>
</plugin>

Show one of the Service:

@VertxGen
@ProxyGen
public interface UserService<T extends User> {

    @Fluent
    UserService register(T element, Handler<AsyncResult<T>> resultHandler) throws IOException;

    @Fluent
    UserService validate(UUID id, Handler<AsyncResult<T>> resultHandler) throws IOException;

    @Fluent
    UserService cancel(UUID id, Handler<AsyncResult<T>> resultHandler);

    @Fluent
    UserService update(UUID id, T element, Handler<AsyncResult<T>> resultHandler);

    @Fluent
    UserService getByJwt(String jwt, Handler<AsyncResult<T>> resultHandler);

    @Fluent
    UserService findById(UUID id, Handler<AsyncResult<T>> resultHandler);

    @Fluent
    UserService findByEmail(String email, Handler<AsyncResult<T>> resultHandler);

    @Fluent
    UserService findAllByState(State state, Handler<AsyncResult<List<T>>> resultHandler);

    @Fluent
    UserService findAllByCreateTimeBetween(Instant from, Instant to, Handler<AsyncResult<List<T>>> resultHandler);

    @Fluent
    UserService findAllByCancelledTimeBetween(Instant from, Instant to, Handler<AsyncResult<List<T>>> resultHandler);
}

And when using mvn package -X -f pom.xml, get an error:

[ERROR] -> [Help 1]
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.7.0:compile (default-compile) on project user-module: Compilation failure
Annotation processor 'io.vertx.codegen.CodeGenProcessor' not found

	at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:212)
	at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
	at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
	at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:116)
	at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:80)
	at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:51)
	at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
	at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:307)
	at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:193)
	at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:106)
	at org.apache.maven.cli.MavenCli.execute(MavenCli.java:863)
	at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:288)
	at org.apache.maven.cli.MavenCli.main(MavenCli.java:199)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:564)
	at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
	at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
	at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
	at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)
	at org.codehaus.classworlds.Launcher.main(Launcher.java:47)
Caused by: org.apache.maven.plugin.compiler.CompilationFailureException: Compilation failure
Annotation processor 'io.vertx.codegen.CodeGenProcessor' not found

	at org.apache.maven.plugin.compiler.AbstractCompilerMojo.execute(AbstractCompilerMojo.java:1161)
	at org.apache.maven.plugin.compiler.CompilerMojo.execute(CompilerMojo.java:168)
	at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:134)
	at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:207)
	... 21 more
[ERROR] 
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException
[ERROR] 
[ERROR] After correcting the problems, you can resume the build with the command
[ERROR]   mvn <goals> -rf :user-module

What's more, I found when I use

        <dependency>
            <groupId>io.vertx</groupId>
            <artifactId>vertx-service-proxy</artifactId>
            <classifier>processor</classifier>
        </dependency>

and

<dependency>
    <groupId>io.vertx</groupId>
    <artifactId>vertx-codegen</artifactId>
</dependency>

together, my module-info.java will get a Module xxx reads package 'io.vertx.codegen' from both 'vertx.codegen' and 'vertx.codegen' & Ambiguous module reference: vertx.codege error... What that mean?

`toJson` required in a `DataObject`, or will fail to generate service proxy

A DataObject without toJson:

package io.vertx.example.entity;

import io.vertx.codegen.annotations.DataObject;
import io.vertx.core.json.JsonObject;

@DataObject
public class User {
  public User(JsonObject json) {
    // ...
  }
}

Fail to run ./gradlew build:

> Task :compileJava FAILED
Processed element io.vertx.example.service.impl.UserServiceImpl is in an implementation package
Could not generate model for io.vertx.example.service.UserService#find(io.vertx.core.json.JsonObject,io.vertx.core.Handler<io.vertx.core.AsyncResult<java.util.List<io.vertx.example.entity.User>>>): type io.vertx.core.Handler<io.vertx.core.AsyncResult<java.util.List<io.vertx.example.entity.User>>> is not legal for use for a parameter in code generation
io.vertx.codegen.GenException: type io.vertx.core.Handler<io.vertx.core.AsyncResult<java.util.List<io.vertx.example.entity.User>>> is not legal for use for a parameter in code generation
        at io.vertx.codegen.ClassModel.checkParamType(ClassModel.java:275)
        at io.vertx.codegen.ClassModel.getParams(ClassModel.java:1045)
        at io.vertx.codegen.ClassModel.createMethod(ClassModel.java:893)
        at io.vertx.codegen.ClassModel.lambda$traverseType$12(ClassModel.java:742)
...

While with toJson, it's OK:

@DataObject
public class User {
  public User(JsonObject json) {
    // ...
  }

+ public JsonObject toJson() {
+   return JsonObject.mapFrom(this);
+ }
}

Javascript codegen is missing import

@marcelalburg commented on Mon May 30 2016

Hello,

if you build you own data objects and generate a proxy/service from it, the generated javascript file is missing a import/definition.

you can see this p.e. here : https://github.com/englishtown/vertx-elasticsearch-service/blob/develop/src/main/resources/vertx-elasticsearch-service-js/elastic_search_admin_service.js

if you add in this example:

var com = Packages.com;

it loads fine.

Thanks
Marcel


@vietj commented on Fri Jan 13 2017

can you open this issue in the vertx-service-proxy project instead ? that's were JS is generated

Service Proxies handling Observables

This is relate with issue #5, which has been closed (but incorrectly in my opinion):

previous issue: #5

While the generated proxies offer an Observable handing implementation on the client side, there is no way for the handler to put and observable (coming from the service implementation side) in the eventbus for a reply.

So right now on the service implementation side, if you're doing any operations with an Observable you need to subscribe to those observables first, so that you then pass a concrete entity class into the handler.

I'm sure it is possible to put observable in the event bus, as I've done it before using Vertx Codecs/Buffer, but I'm not entirely sure what would be the best way to do it, once you enter the realm of dealing with the proxy generated handler classes?

Are you guys going to add such a feature?

Optimised marshalling

As well as standard marshalling over json, we could provide an optional optimised marshaller for service proxy which uses an efficient binary format for proxy event bus traffic.

ProxyHelper is unable to construct a mongo service

private static Constructor getConstructor(Class clazz, Class... types) {
try {
return clazz.getDeclaredConstructor(types);
} catch (NoSuchMethodException e) {
throw new IllegalStateException("Cannot find constructor on: " + clazz.getName(), e);
}
}

is now trying to return an io.vertx.ext.mongo.MongoServiceVertxProxyHandler constructor with 4 parameters, although only 3 parameters version of constructor exists in the latest. as a result of it IllegalStateException is thrown from the code above.

extends interface

Hi! I would like to extends an interface to have a set implemented methods, but i got

Error:(45, 8) java: ServiceVertxEBProxy is not abstract and does not override abstract method delete(it.hoop.server.model.BaseEntity,io.vertx.core.Handler) in it.hoop.server.service.DaoService

Is possibile to generate ProxyClass calling super methods???

vertx service proxy exposed to eventbusbridge

As far as I understand, due to the 'header' and 'body' sent to proxies, the proxy addresses cannot be used to expose the services using an eventbusbridge. The reason being: there is no header sent.
It would be nice to have service proxies to be able to expose their address, so they can be accessed from 'outside' (using the eventbusbridge). This could probably be a switch on the Proxygen annotation
There may be different strategies to do this:

  1. check if there is a 'header'. If not, check if the json message (body) contains a 'header' and 'body' field. If there is a header, well, that's how it's now. If there isn't, but there is a 'header' and 'body' in the message itself, things are pretty easy to 'extract'.
  2. different addresses may be used for the 'exposed' and 'concealed' version - configurable in the Proxygen annotation again?
  3. ...?

Rxified Service Proxies

It would be great to support Rxified methods in Service Interfaces:

default:

  @Fluent
  MongoService insert(String collection, JsonObject document, Handler<AsyncResult<String>> resultHandler);

Observable:

  ObservableFuture<String> insert(String collection, JsonObject document);

Service Proxies really do reduce boilerplate but unfortunately it does not work well with vertx-rx.

Connection timeouts

Inactive connections should be automatically timed out and closed otherwise they can be left hanging if the client disappears.

proxyHandler.setConsumer(consumer) in 3.5

I used to have:
MessageConsumer consumer = getVertx().eventBus().consumer(eventBusAddress.value()).handler(proxyHandler);
proxyHandler.setConsumer(consumer);

when switched to 3.5 there is no setConsumer(), that is the recommendation about it?

Thanks.

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.