tried everything, but MainVerticle does not like DI @Inject

860 views
Skip to first unread message

js

unread,
Jan 30, 2018, 5:26:53 PM1/30/18
to vert.x

error at startup:

SEVERE: Failed in deploying verticle
java.lang.InstantiationException: com.example.demo.MainVerticle
Caused by: java.lang.NoSuchMethodException: com.example.demo.MainVerticle.<init>()

tried just @Inject annotation on the field, just on the constructor and on both

@Inject
private SomeManager someManager ;


@Inject
public MainVerticle(SomeManager someManager ) {
this.someManager = SomeManager;
}


tried both imports
import javax.inject.Inject;
import com.google.inject.Inject;


tried several version of 2 diff guice dependencies

<dependency>
<groupId>com.englishtown.vertx</groupId>
<artifactId>vertx-guice</artifactId>
<version>2.3.1</version>
</dependency>

<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>4.1.0</version>
</dependency>


Erick Johnson

unread,
Jan 31, 2018, 3:58:11 AM1/31/18
to vert.x
I'm playing around with using Vertx with Guice and Grpc. In order to simplify the already difficult dependency management process, I'm avoiding using glue projects like vertx-guice, and instead just managing the depencies manually and it's working well so far.

Here is a snippet of my HelloWorld.java launcher, most of the lines here are uninteresting for your question but notice the injector creation at the top of main(), and the verticle deployment code in `deployVerticles`. Specifically see how the injected Vertx instance `ijVertx` is used to deploy the verticles.

package io.vos.vertx;

import io.vos.service.blob.BlobModule;
import com.beust.jcommander.JCommander;
import com.beust.jcommander.Parameter;
import com.google.inject.Guice;
import com.google.inject.Injector;
import io.vertx.core.DeploymentOptions;
import io.vertx.core.Verticle;
import io.vertx.core.Vertx;
import io.vertx.core.json.JsonObject;
import io.vertx.core.logging.Logger;
import io.vertx.core.logging.LoggerFactory;

import java.util.AbstractMap.SimpleEntry;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.inject.Inject;


/**
 * For Vertx Docs:
 * @see http://vertx.io/docs/vertx-core/java
 * @see http://vertx.io/docs/apidocs/io/vertx/core/package-summary.html
 * @see http://vertx.io/docs/apidocs/io/vertx/core/Vertx.html
 *
 * For Vertx Examples:
 * @see https://github.com/vert-x3/vertx-examples/tree/master/core-examples
 */

public class HelloWorld {

 
// Using the JCommander command line parameter parser
 
// see http://jcommander.org/#_overview
 
@Parameter(names = { "--some-int" }, description = "Some random int")
 
private Integer someInt = 0;

 
@Parameter(names = { "--some-string", "-S"}, description = "Some string")
 
private String someString = "default";

 
private static final Map<String, Object> VRTCL_CONFIG =
     
Stream.of(
         
new SimpleEntry<>("storage.cassandra.host", "localhost"),
         
new SimpleEntry<>("storage.cassandra.port", 9042),
         
new SimpleEntry<>("grpc.port", 50051))
     
.collect(Collectors.toMap(SimpleEntry::getKey, SimpleEntry::getValue));

 
private final Set<Verticle> ijVerticles;
 
private final Vertx ijVertx;

 
@Inject
 
HelloWorld(
     
Vertx vertx,
     
Set<Verticle> verticles) {
    ijVertx
= vertx;
    ijVerticles
= verticles;
 
}

 
private void deployVerticles() {
   
DeploymentOptions options =
       
new DeploymentOptions()
       
.setConfig(new JsonObject(VRTCL_CONFIG))
       
.setWorker(true);

   
for (Verticle v : ijVerticles) {
      LOG
.info("deploying --> " + v.getClass().getName());
      ijVertx
.deployVerticle(v, options);
   
}
 
}

 
// Use runtime Java system properties to select a LogDelegateFactory
 
// @see http://vertx.io/docs/vertx-core/java/#_using_another_logging_framework
 
// @see http://vertx.io/docs/apidocs/io/vertx/core/spi/logging/LogDelegateFactory.html
 
//
 
// For slf4j, make sure to include //external:slf4fj and run with:
 
// $  bazel run \
 
//   --jvmopt='-Dvertx.logger-delegate-factory-class-name=io.vertx.core.logging.SLF4JLogDelegateFactory' \
 
//   //java/io/vos/vertx:HelloWorld
 
private static final Logger LOG = LoggerFactory.getLogger(HelloWorld.class);

 
public static void main(String[] args) {
   
final Injector i = Guice.createInjector(
       
new VertxModule(),

       
// For more examples see:
       
// https://github.com/vert-x3/vertx-examples/tree/master/core-examples
       
new BlobModule());

   
HelloWorld hwServer = i.getInstance(HelloWorld.class);
   
JCommander.newBuilder()
       
.addObject(hwServer)
       
.build()
       
.parse(args);
    LOG
.info(String.format("HelloWorld: parameter --some-int: %d", hwServer.someInt));
    LOG
.info(String.format("HelloWorld: parameter --some-string: %s", hwServer.someString));

    hwServer
.deployVerticles();

   
final Vertx v = hwServer.ijVertx;

   
// Create an HTTP server which simply returns "Hello World!" to each request.
    LOG
.info("creating webserver");
    v
.createHttpServer().requestHandler(req -> req.response().end("Hello World!")).listen(8080);

   
// http://vertx.io/docs/vertx-core/java/#_writing_verticles
   
// http://vertx.io/docs/apidocs/io/vertx/core/Vertx.html#deployVerticle-io.vertx.core.Verticle-
   
// See deploy examples:
   
// https://github.com/vert-x3/vertx-examples/blob/master/core-examples/src/main/java/io/vertx/example/core/verticle/deploy/DeployExample.java
    LOG
.info("deploying HttpClientVerticle");
    v
.deployVerticle(new HttpClientVerticle());

    LOG
.info("deploying hazelcast instance member");
    v
.deployVerticle(new HazelcastVerticle());

    LOG
.info("deploying ruby verticle");
    v
.deployVerticle("ruby/io/vos/vertx/hello_verticle.rb");
 
}

}


the modules are defined like so:

package io.vos.service.blob;

import com.google.inject.AbstractModule;
import com.google.inject.multibindings.Multibinder;

import io.grpc.BindableService;

import io.vertx.core.Verticle;

public final class BlobModule extends AbstractModule {

 
@Override
 
protected void configure() {
   
Multibinder<Verticle> verticleBinder = Multibinder.newSetBinder(binder(), Verticle.class);
    verticleBinder
.addBinding().to(BlobVerticle.class);

   
Multibinder<BindableService> serviceBinder =
       
Multibinder.newSetBinder(binder(), BindableService.class);
    serviceBinder
.addBinding().to(BlobService.class);
 
}
}


and finally an example Verticle like so with some dummy injected values:

package io.vos.service.blob;

import io.vertx.core.Vertx;
import io.vertx.core.eventbus.EventBus;
import io.vertx.core.AbstractVerticle;
import io.vertx.core.logging.Logger;
import io.vertx.core.logging.LoggerFactory;

import javax.inject.Inject;

public class BlobVerticle extends AbstractVerticle {

 
private static final Logger LOG = LoggerFactory.getLogger(BlobVerticle.class);

 
private final BlobServer ijServer;

 
@Inject
 
BlobVerticle(BlobServer server) {
    ijServer
= server;
 
}

 
@Override
 
public void start()
     
throws Exception {
    LOG
.info("starting blob RPC service");

   
int port = config().getInteger("grpc.port");
    ijServer
.start(port);
 
}
}

Adrian Gonzalez

unread,
Jan 31, 2018, 8:57:28 AM1/31/18
to vert.x
It's a little hard to say without seeing a full reproducer, but my guess would be when deploying your verticle you are not providing the `java-guice:`
verticle prefix to the identifier.  This tells vert.x which VerticleFactory to use.  If you don'y see GuiceVerticleFactory in your stack trace then that is likely the problem.

There is an example of how to programmatically deploy your verticle here.

js

unread,
Jan 31, 2018, 12:53:53 PM1/31/18
to vert.x
Erik, 
thanks for the post.. but i'm new to vertx and your helloworld example is a little to complicated for me at this point.
Interestingly, your using guice direct and not englishtown .. yet your still able to use the @Inject annotation. (so it seems like you do not have a fully manual DI)
Confusingly, some DI vertx github examples use guice direct and some use englishtown.
I have'nt been able to find info on which is best/newest or what the diff are between them.
Your also using guice Injector, but none of the github examples i've seen require that class for guice DI

Adrian,
I assume englishtown's motivation was that guice could not be used direct by vertx at some point in the past?
Has that changed (are new vertx version able to use guice w/out your jar)?

i'm coming from a spring background where DI annotation just needed to be added to the field definition:

@Autowired
private SomeClass someClass
(no constructor.. super simple)

vertx seems to req @Inject at the constructor but none of the examples seem to work.
(i'm using the "demo" sample app generated from vertx.io)

stack trace does not mention GuiceVerticleFactory

using com.google.inject dependency:

java.lang.InstantiationException: com.example.demo.MainVerticle
at java.lang.Class.newInstance(Class.java:427)
at io.vertx.core.impl.JavaVerticleFactory.createVerticle(JavaVerticleFactory.java:44)
at io.vertx.core.impl.DeploymentManager.createVerticles(DeploymentManager.java:234)
at io.vertx.core.impl.DeploymentManager.lambda$doDeployVerticle$2(DeploymentManager.java:207)
at io.vertx.core.impl.FutureImpl.setHandler(FutureImpl.java:81)
at io.vertx.core.impl.DeploymentManager.doDeployVerticle(DeploymentManager.java:176)
at io.vertx.core.impl.DeploymentManager.doDeployVerticle(DeploymentManager.java:148)
at io.vertx.core.impl.DeploymentManager.deployVerticle(DeploymentManager.java:136)
at io.vertx.core.impl.VertxImpl.deployVerticle(VertxImpl.java:650)
at io.vertx.core.impl.launcher.commands.VertxIsolatedDeployer.deploy(VertxIsolatedDeployer.java:46)
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 io.vertx.core.impl.launcher.commands.ClasspathHandler.deploy(ClasspathHandler.java:164)
at io.vertx.core.impl.launcher.commands.RunCommand.deploy(RunCommand.java:401)
at io.vertx.core.impl.launcher.commands.RunCommand.run(RunCommand.java:274)
at io.vertx.core.impl.launcher.VertxCommandLauncher.execute(VertxCommandLauncher.java:230)
at io.vertx.core.impl.launcher.VertxCommandLauncher.dispatch(VertxCommandLauncher.java:365)
at io.vertx.core.impl.launcher.VertxCommandLauncher.dispatch(VertxCommandLauncher.java:328)
at io.vertx.core.Launcher.main(Launcher.java:49)
Caused by: java.lang.NoSuchMethodException: com.example.demo.MainVerticle.<init>()
at java.lang.Class.getConstructor0(Class.java:3082)
at java.lang.Class.newInstance(Class.java:412)


-------

using com.englishtown.vertx dependency:

java.lang.InstantiationException: com.example.demo.MainVerticle
at java.lang.Class.newInstance(Class.java:427)
at io.vertx.core.impl.JavaVerticleFactory.createVerticle(JavaVerticleFactory.java:44)
at io.vertx.core.impl.DeploymentManager.createVerticles(DeploymentManager.java:234)
at io.vertx.core.impl.DeploymentManager.lambda$doDeployVerticle$2(DeploymentManager.java:207)
at io.vertx.core.impl.FutureImpl.setHandler(FutureImpl.java:81)
at io.vertx.core.impl.DeploymentManager.doDeployVerticle(DeploymentManager.java:176)
at io.vertx.core.impl.DeploymentManager.doDeployVerticle(DeploymentManager.java:148)
at io.vertx.core.impl.DeploymentManager.deployVerticle(DeploymentManager.java:136)
at io.vertx.core.impl.VertxImpl.deployVerticle(VertxImpl.java:650)
at io.vertx.core.impl.launcher.commands.VertxIsolatedDeployer.deploy(VertxIsolatedDeployer.java:46)
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 io.vertx.core.impl.launcher.commands.ClasspathHandler.deploy(ClasspathHandler.java:164)
at io.vertx.core.impl.launcher.commands.RunCommand.deploy(RunCommand.java:401)
at io.vertx.core.impl.launcher.commands.RunCommand.run(RunCommand.java:274)
at io.vertx.core.impl.launcher.VertxCommandLauncher.execute(VertxCommandLauncher.java:230)
at io.vertx.core.impl.launcher.VertxCommandLauncher.dispatch(VertxCommandLauncher.java:365)
at io.vertx.core.impl.launcher.VertxCommandLauncher.dispatch(VertxCommandLauncher.java:328)
at io.vertx.core.Launcher.main(Launcher.java:49)
Caused by: java.lang.NoSuchMethodException: com.example.demo.MainVerticle.<init>()
at java.lang.Class.getConstructor0(Class.java:3082)
at java.lang.Class.newInstance(Class.java:412)


----------------

so there must be some setup that need be performed for vertx DI to work

Adrian's link shows:
@Override
public void setUp() throws Exception {
super.setUp();
CompletableFuture<Void> future = new CompletableFuture<>();
JsonObject config = new JsonObject().put("guice_binder", Binder.class.getName());
vertx.deployVerticle("java-guice:" + SimpleVerticle.class.getName(), new DeploymentOptions().setConfig(config), result -> {
if (result.succeeded()) {
future.complete(null);
} else {
future.completeExceptionally(result.cause());
}
});
future.get(2, TimeUnit.SECONDS);
} ------- one would assume that "setup" is done in the MainVerticle, but apparently thats not the case all i want is for the MainVerticle (or whatever the main bootstrap class is) to have the start method call some other utility type classes to bootstrap the app w/ routes, a web server and other environment setup stuff. Most examples have all this dome in the MainVerticle, but i think thats best organized in diff utility classes -----------
public class MainVerticle extends AbstractVerticle {

private final UtilityClassToSetupAppStartupStuff startupStuff;

@Inject
MainVerticle(UtilityClassToSetupAppStartupStuff startupStuff) {
this.startupStuff = startupStuff;
}

@Override
public void start() {
Router router = Router.router(vertx);
startupStuff.defineRoutes(router);
vertx.createHttpServer().requestHandler(router::accept).listen(8080);
}

}

spring is getting way too complicated and play is simply inoperable.
vertx seems to be the perfect intersection of framework and manual code

i only hope i can find enough documentation and examples to figure it out because i have soooo many basic questions

-js



Erick Johnson

unread,
Feb 1, 2018, 4:16:51 AM2/1/18
to vert.x
Hi JS

re: "Your also using guice Injector, but none of the github examples i've seen require that class for guice DI"

I'd very much encourage you to take a look at using Guice without any additional abstraction around it. I promise that any examples you've seen using guice are using an injector at some point to build the object graph.

Try checking out the Guice getting started guide here:

https://github.com/google/guice/wiki/GettingStarted

Re: "Confusingly, some DI vertx github examples use guice direct and some use englishtown.


I have'nt been able to find info on which is best/newest or what the diff are between them."

When I first started looking at Guice+Vertx I also came across that project. IIRC though, I abandoned that route because I had no interest in deploying verticles on the command line, and dropping the extra dependency was just simpler than managing the Guice dependency transitively. Without the command line deployment requirement, it seemed like there was no benefit to using it.

Someone please correct me if I'm wrong

Dan O'Reilly

unread,
Feb 1, 2018, 10:20:12 AM2/1/18
to ve...@googlegroups.com
The vertx-guice project doesn't have a CLI deployment requirement. You just need to use the "java-guice:" prefix before the canonical name of your Verticle when you call vertx.deployVerticle(), and ensure that GuiceVerticleFactory is in your classpath. That should be as simple as including vertx-guice in your pom.xml.

--
You received this message because you are subscribed to the Google Groups "vert.x" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vertx+un...@googlegroups.com.
Visit this group at https://groups.google.com/group/vertx.
To view this discussion on the web, visit https://groups.google.com/d/msgid/vertx/77d3955c-f951-4360-9c16-22f23a164a07%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

js

unread,
Feb 1, 2018, 1:29:40 PM2/1/18
to vert.x
thx Erik,

i went over the "getting started w/ guice" guide as per your instructions:

their example of a relationship between the relater and the relatee (or an implementation of such) is a little convoluted

all i want is for a House class to have an injected reference to a Roof class 

little more googling and all i had to do was place the following at the top of the house class:

Injector injector = Guice.createInjector();
Roof roof= injector.getInstance(Roof.class);

no @Inject annotation, no configure overrides, no AbstractModule extension, no MultiBinder, no constuctors, no code required in the Roof class

its simple, it works and its just 2 lines

i'm happy.. until someone tells me i'm not supposed to do it that way






 

Dan O'Reilly

unread,
Feb 1, 2018, 3:53:44 PM2/1/18
to ve...@googlegroups.com
You're not supposed to do it that way :). The Guice best practices guide recommends you use constructor injection to create immutable objects whenever possible (https://github.com/google/guice/wiki/MinimizeMutability#minimize-mutability).

The Injector instance should only be used in the boostrapping code for your application, and potentially in some other infrastructure components. If you use vertx-guice, it's only used in the GuiceVerticleFactory infrastructure component to create an instance of your Verticle.

It's not good design to have the House class internally create an Injector to inject a Roof instance. You have no way to configure the Injector with additional modules without editing the House class directly, which isn't always practical. Let's say you want to inject a mock Roof implementation for tests, but use a real one for production. You don't have an easy way to do it when you directly create an Injector inside the House class. 

You'll also need to duplicate this Injector creation code everywhere you want to inject anything, which means you end up with many unrelated Injector instances spread throughout your code, and every time you need a new Module you'll need to track them all down to add the new Module to the createInjector() call. This also means won't ever be able to inject anything as a Singleton.

--
You received this message because you are subscribed to the Google Groups "vert.x" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vertx+un...@googlegroups.com.
Visit this group at https://groups.google.com/group/vertx.

js

unread,
Feb 1, 2018, 7:07:33 PM2/1/18
to vert.x


somehow i knew that was coming


i guess i need work on my immutability


thx Dan


Reply all
Reply to author
Forward
0 new messages