how to deploy a vert.x verticle at runtime? - java

my project is generated by http://start.vertx.io
my http handler:
// ...
public void handle(RoutingContext ctx) {
String verticleName = ctx.queryParams().get("v");
ctx.vertx().deployVerticle(verticleName);
ctx.response().end();
}
// ...
but it reports error
java.lang.RuntimeException: Resource not found: verticles/TestVerticle.java
at io.vertx.core.impl.verticle.CompilingClassLoader.<init>(CompilingClassLoader.java:68)
at io.vertx.core.impl.JavaVerticleFactory.createVerticle(JavaVerticleFactory.java:37)
at io.vertx.core.impl.VerticleManager.doDeployVerticle(VerticleManager.java:217)
at io.vertx.core.impl.VerticleManager.doDeployVerticle(VerticleManager.java:193)
at io.vertx.core.impl.VerticleManager.doDeployVerticle(VerticleManager.java:180)
at io.vertx.core.impl.VerticleManager.deployVerticle(VerticleManager.java:156)
at io.vertx.core.impl.VertxImpl.deployVerticle(VertxImpl.java:623)
at io.vertx.core.impl.VertxImpl.deployVerticle(VertxImpl.java:608)

By default the verticle name should be a fully-qulified class name that has a no-args constructor and implements Verticle (or extends one of its implementors). e.g.
package demo;
import io.vertx.core.AbstractVerticle;
public class MyVerticle extends AbstractVerticle {
#Override
public void start() throws Exception {
// ...
}
}
Then you can do:
vertx.deployVerticle("demo.MyVerticle");
If you want to use another mechanism you can create a custom VerticleFactory (https://vertx.io/docs/vertx-service-factory/java/) and use your own logic. e.g.
package demo;
import io.vertx.core.Promise;
import io.vertx.core.Verticle;
import io.vertx.core.spi.VerticleFactory;
import java.util.concurrent.Callable;
public class CustomVerticleFactory implements VerticleFactory {
#Override
public String prefix() {
return "custom";
}
#Override
public void createVerticle(String verticleName, ClassLoader classLoader, Promise<Callable<Verticle>> promise) {
if (verticleName.equals("custom:x")) {
promise.complete(() -> new MyVerticle());
} else {
promise.fail("...");
}
}
}
Load it to your Vertx instance:
vertx.registerVerticleFactory(new CustomVerticleFactory());
And then you can do:
vertx.deployVerticle("custom:x");

Found the right way.
I should start the app with -Xbootclasspath/a:.
Then the class loader can found java source files(XXXVerticle.java) at . (working dir)

Related

TypeTransformer applyAdviceToMethod(isConstructor() doesn't works in opentelemetry extensions

I'm trying to add spans when constructor of some class called. I'm using opentelemetry javaagent and extensions to add tracing to my application.
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.matcher.ElementMatchers;
import static net.bytebuddy.matcher.ElementMatchers.isConstructor;
import static net.bytebuddy.matcher.ElementMatchers.named;
public class ClassConstructorInstrumentation implements TypeInstrumentation {
#Override
public ElementMatcher<TypeDescription> typeMatcher() {
return ElementMatchers
.namedOneOf("org.example.ServiceManagerDummy");
}
#Override
public void transform(TypeTransformer transformer) {
transformer.applyAdviceToMethod(
isConstructor(),
this.getClass().getName() + "$ConstructorSpanCreateAdvice");
// transformer.applyAdviceToMethod(
// named("dummyMethod"),
// this.getClass().getName() + "$ConstructorSpanCreateAdvice");
}
#SuppressWarnings("unused")
public static class ConstructorSpanCreateAdvice {
#Advice.OnMethodEnter
public static void onEnter() {
System.out.println("START SPAN ");
}
#Advice.OnMethodExit(onThrowable = Throwable.class)
public static void onExit(
#Advice.Thrown Throwable throwable
) {
System.out.println("END SPAN ");
}
}
}
public class ServiceManagerDummy {
public ServiceManagerDummy() {
System.out.println("SERVICE MANAGER CONSTR");
dummyMethod();
}
private void dummyMethod() {
System.out.println("DUMMY METHOD CALLED");
}
}
I'm using a simple configuration as above just to verify that when the constructor was called my advice method log it. But when it configured to add some logs when the constructor was called, I received nothing in the log. But when I add config for method calling (commented code) it works. What's wrong in my configuration?
What Byte Buddy would normally do would be to wrap the constructor in a try-finally-block. For a constructor, that is not possible as the super method call cannot be wrapped in such a block. "onThrowable" is therefore not possible for constructors.

Py4J Callback Interface throws "Invalid interface name" when the packaged .jar is used as a plugin

My code is exactly the same as the example shown on py4j website:
Implementing Java Interfaces from Python
Except my classes are all in the same src.main.java package
(see below for the code)
Problem:
If I do a gradle fatjar build with ListenerApplication as main, then execute the jar, everything works fine. If I do a gradle fatjar build and instead access the code via a plugin interface, I get the following error:
Py4JError: An error occurred while calling o0.registerListener. Trace:
py4j.Py4JException: Invalid interface name: ExampleListener
at py4j.Protocol.getPythonProxy(Protocol.java:429)
at py4j.Protocol.getObject(Protocol.java:311)
at py4j.commands.AbstractCommand.getArguments(AbstractCommand.java:82)
at py4j.commands.CallCommand.execute(CallCommand.java:77)
at py4j.GatewayConnection.run(GatewayConnection.java:238)
at java.lang.Thread.run(Thread.java:748)
Question: Why does Py4J have problems finding "ExampleListener" when the .jar is run as a plugin and not as an application? I can even add :
public String classtest() throws Exception {
System.out.println("classtest called");
Class<?> py = Class.forName("ExampleListener");
return py.toString();
}
to the ListenerApplication, which will return the correct interface both when run as plugin and as application! The interesting thing is, if I run the program plus plugin from netbeans IDE, everything works fine! Does Netbeans somehow expose the interface, while the application run directly, does not?
Plugin interface
import org.micromanager.MenuPlugin;
import org.micromanager.Studio;
import org.scijava.plugin.Plugin;
import org.scijava.plugin.SciJavaPlugin;
import py4j.GatewayServer;
#Plugin(type = MenuPlugin.class)
public class Py4JPluginInterface implements MenuPlugin, SciJavaPlugin{
private static final String menuName = "Simpletest_gradle";
private static final String tooltipDescription = "py4j gateway";
private static final String version = "0.1";
private static final String copyright = "copyright";
#Override
public String getSubMenu() {
return "Simpletest_gradle";
}
#Override
public void onPluginSelected() {
GatewayServer gatewayServer = new GatewayServer(new ListenerApplication());
gatewayServer.start();
System.out.println("Gateway Started at IP:port = "+gatewayServer.getAddress()+":"+gatewayServer.getPort());
}
#Override
public void setContext(Studio app) {
}
#Override
public String getName() {
return menuName;
}
#Override
public String getHelpText() {
return tooltipDescription;
}
#Override
public String getVersion() {
return version;
}
#Override
public String getCopyright() {
return copyright;
}
}
The interface:
//py4j/examples/ExampleListener.java
package py4j.examples;
public interface ExampleListener {
Object notify(Object source);
}
The application:
package py4j.examples;
import py4j.GatewayServer;
import java.util.ArrayList;
import java.util.List;
public class ListenerApplication {
List<ExampleListener> listeners = new ArrayList<ExampleListener>();
public void registerListener(ExampleListener listener) {
listeners.add(listener);
}
public void notifyAllListeners() {
for (ExampleListener listener: listeners) {
Object returnValue = listener.notify(this);
System.out.println(returnValue);
}
}
#Override
public String toString() {
return "<ListenerApplication> instance";
}
public static void main(String[] args) {
ListenerApplication application = new ListenerApplication();
GatewayServer server = new GatewayServer(application);
server.start(true);
}
}
The python listener
from py4j.java_gateway import JavaGateway, CallbackServerParameters
class PythonListener(object):
def __init__(self, gateway):
self.gateway = gateway
def notify(self, obj):
print("Notified by Java")
print(obj)
gateway.jvm.System.out.println("Hello from python!")
return "A Return Value"
class Java:
implements = ["py4j.examples.ExampleListener"]
if __name__ == "__main__":
gateway = JavaGateway(
callback_server_parameters=CallbackServerParameters())
listener = PythonListener(gateway)
gateway.entry_point.registerListener(listener)
gateway.entry_point.notifyAllListeners()
gateway.shutdown()
For those who are interested, this was a class loader issue, which is apparently common for plugin/OSGI apps.
See the maintainer's response:
https://github.com/bartdag/py4j/issues/339#issuecomment-473655738
I simply added the following to the Java-side ListenerApplication constructor:
RootClassLoadingStrategy rmmClassLoader = new RootClassLoadingStrategy();
ReflectionUtil.setClassLoadingStrategy(rmmClassLoader);

sharing store data between extensions in JUNIT5

Is there anyway we can share data between different extensions in JUNIT 5 using store
Example
public class Extension1{
beforeAllCallback(){
getStore(GLOBAL).put(projectId,"112");
}
}
public class Extension2{
beforeTestExecutionCallback(){
System.out.println("projectId="+getStore(GLOBAL).get(projectId));
}
}
Yes, two extensions can share state via the Store as follows.
Note, however, that you may wish to store the shared state in the root context Store if you want the state to be accessible across test classes.
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.BeforeAllCallback;
import org.junit.jupiter.api.extension.BeforeTestExecutionCallback;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.ExtensionContext.Namespace;
#ExtendWith({ Extension1.class, Extension2.class })
public class Tests {
#Test
void test() {
// executing this results in the following being printed to SYS_OUT.
// PROJECT_ID=112
}
}
class Extension1 implements BeforeAllCallback {
public static final String PROJECT_ID = Extension1.class.getName() + ".PROJECT_ID";
#Override
public void beforeAll(ExtensionContext context) throws Exception {
context.getStore(Namespace.GLOBAL).put(PROJECT_ID, "112");
}
}
class Extension2 implements BeforeTestExecutionCallback {
#Override
public void beforeTestExecution(ExtensionContext context) throws Exception {
System.out.println("PROJECT_ID=" + context.getStore(Namespace.GLOBAL).get(Extension1.PROJECT_ID));
}
}

Loading Class from Jar File : java.lang.InstantiationException

I got this code to instantiate a Life class from jar file:
import com.life.Life;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
public class Main {
public static void main(String[] args) {
try{
File file = new File("Life.jar");
URL url = file.toURI().toURL();
URL[] urls = new URL[]{url};
ClassLoader cl = new URLClassLoader(urls);
Class cls = cl.loadClass("com.life.Life");
Life life = (Life) cls.newInstance();
System.out.println("Message: "+life.getMessage());
}catch(Exception e){
e.printStackTrace();
}
}
}
Here's the content of the Life.jar
public class Life {
public String getMessage(){
return "Life is Beautiful!";
}
}
Here's my interface name Life
package com.life;
public interface Life {
public String getMessage();
}
The code above will throw an error:
java.lang.InstantiationException: com.life.Life
at java.lang.Class.newInstance0(Class.java:340)
at java.lang.Class.newInstance(Class.java:308)
at com.Main.main(Main.java:20)
BUILD SUCCESSFUL (total time: 0 seconds)
What's wrong with the code? How to resolve this?
This happened because your interface is also named Life ( java tried to instantiate an interface). Change public interface Life to public interface LifeInterface and then have your class Life implement that like :
public class Life implements LifeInterface
{
#Override
public String getMessage()
{
return "Life is Beautiful!";
}
}

Defining spring #EventListener in an abstract super class

I've stared to use spring's #EventListener annotation to create event handlers that handle my non-spring specific events. Initially everything went pretty well. I used a test to verify that I could put the #EventListener annotation on a method of a abstract class and everything worked as expected.
However, once I started adding generics to the mix I started getting NullPointerExceptions from ApplicationListenerMethodAdapter.java:337.
I've created a test case to illustrate the problem. Currently all the test methods fail with the exception:
java.lang.NullPointerException
at java.lang.Class.isAssignableFrom(Native Method)
at org.springframework.context.event.ApplicationListenerMethodAdapter.getResolvableType(ApplicationListenerMethodAdapter.java:337)
at org.springframework.context.event.ApplicationListenerMethodAdapter.resolveArguments(ApplicationListenerMethodAdapter.java:161)
at org.springframework.context.event.ApplicationListenerMethodAdapter.processEvent(ApplicationListenerMethodAdapter.java:142)
at org.springframework.context.event.ApplicationListenerMethodAdapter.onApplicationEvent(ApplicationListenerMethodAdapter.java:106)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:163)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:136)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:381)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:348)
When I move the #EventListener annotation down to each concrete listener the exception disappears and things behave as expected with the exception of testSendingEventWithGenericsWithExtendedUniquePayload.
Questions
Q1) Is it a valid usage pattern to put #EventListener on a method of a abstract super class? I was hoping to implement common behavior there.
Q2) I read about implementing ResolvableTypeProvider on my event in the spring docs. My understanding was that this would allow me to avoid having to create many concrete subclasses for each payload type. This is what I'm attempting to test in testSendingEventWithGenericsWithExtendedUniquePayload. I'm expecting the event fired in this test to be handled by TestEventWithGenericsExtendedUniquePayloadListener but it's not. Have I misunderstood something here?
Spring: 4.2.4.RELEASE
Java: 1.8.0_65
Thanks for your help
Oliver
Test Code
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.EventListener;
import org.springframework.core.ResolvableType;
import org.springframework.core.ResolvableTypeProvider;
import org.springframework.stereotype.Component;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import static org.springframework.core.ResolvableType.*;
/**
* #author Oliver Henlich
*/
#ContextConfiguration
#RunWith(SpringJUnit4ClassRunner.class)
#DirtiesContext
public class EventListenerTest {
private static final Logger log = LoggerFactory.getLogger(EventListenerTest.class);
#Autowired
protected transient ApplicationEventPublisher applicationEventPublisher;
#Test
public void testSendingEvent1() {
log.info("testSendingEvent1");
// this should go to TestEvent1Listener
applicationEventPublisher.publishEvent(new TestEvent1(new UniquePayload()));
}
#Test
public void testSendingEventWithGenerics() {
log.info("testSendingEventWithGenerics");
// this should go to TestEventWithGenericsListener
applicationEventPublisher.publishEvent(new TestEventWithGenerics<>(new UniquePayload()));
}
#Test
public void testSendingEventWithGenericsWithExtendedUniquePayload() {
log.info("testSendingEventWithGenerics");
// I was expecting this to go to TestEventWithGenericsExtendedUniquePayloadListener
applicationEventPublisher.publishEvent(new TestEventWithGenerics<>(new ExtendedUniquePayload()));
}
#Test
public void testSendingEvent2() {
log.info("testSendingEvent2");
// there is no listener for this one
applicationEventPublisher.publishEvent(new TestEvent2(new UniquePayload()));
}
// LISTENERS --------------------------------------------------------------
interface TestDataEventListener<E extends TestDataEvent> {
#SuppressWarnings("unused")
List<String> handleEvent(E event);
}
abstract static class AbstractTestDataEventListener<E extends TestDataEvent> implements TestDataEventListener<E> {
#Override
#EventListener
public final List<String> handleEvent(E event) {
return onEvent(event);
}
public abstract List<String> onEvent(E event);
}
#Component
static final class TestEvent1Listener extends AbstractTestDataEventListener<TestEvent1> {
#Override
public List<String> onEvent(TestEvent1 event) {
log.info("Listener {} handled {}", this, event);
return Collections.emptyList();
}
}
#Component
static final class TestEventWithGenericsListener extends AbstractTestDataEventListener<TestEventWithGenerics> {
#Override
public List<String> onEvent(TestEventWithGenerics event) {
log.info("Listener {} handled {}", this, event);
return Collections.emptyList();
}
}
#Component
static final class TestEventWithGenericsExtendedUniquePayloadListener extends AbstractTestDataEventListener<TestEventWithGenerics<ExtendedUniquePayload>> {
#Override
public List<String> onEvent(TestEventWithGenerics<ExtendedUniquePayload> event) {
log.info("Listener {} handled {}", this, event);
return Collections.emptyList();
}
}
// EVENTS -----------------------------------------------------------------
interface TestDataEvent<T extends Unique> extends ResolvableTypeProvider {
T load();
}
abstract static class AbstractTestDataEvent<T extends Unique> implements TestDataEvent<T> {
protected final UUID uuid;
private final ResolvableType resolvableType;
public AbstractTestDataEvent(T uniqueObject) {
uuid = uniqueObject.getUuid();
ResolvableType temp = ResolvableType.forClass(getClass());
if (temp.hasGenerics()) {
temp = forClassWithGenerics(getClass(), forInstance(uniqueObject));
}
resolvableType = temp;
log.info("class = {} resolvableType = {}", getClass(), resolvableType);
}
#Override
public ResolvableType getResolvableType() {
return resolvableType;
}
}
static final class TestEvent1 extends AbstractTestDataEvent<UniquePayload> {
public TestEvent1(UniquePayload uniqueObject) {
super(uniqueObject);
}
#Override
public UniquePayload load() {
return new UniquePayload(uuid);
}
}
static final class TestEvent2 extends AbstractTestDataEvent<UniquePayload> {
public TestEvent2(UniquePayload uniqueObject) {
super(uniqueObject);
}
#Override
public UniquePayload load() {
return new UniquePayload(uuid);
}
}
static final class TestEventWithGenerics<T extends UniquePayload> extends AbstractTestDataEvent<T> {
public TestEventWithGenerics(T uniqueObject) {
super(uniqueObject);
}
#Override
public T load() {
return (T) new UniquePayload(uuid);
}
}
static class UniquePayload implements Unique {
private final UUID uuid;
public UniquePayload() {
this(UUID.randomUUID());
}
public UniquePayload(UUID uuid) {
this.uuid = uuid;
}
#Override
public UUID getUuid() {
return uuid;
}
}
static class ExtendedUniquePayload extends UniquePayload {
}
interface Unique {
UUID getUuid();
}
#Configuration
#ComponentScan(basePackageClasses = EventListenerTest.class)
public static class ContextConfiguration {
}
}

Categories