I want to test Quarkus and the native image for Docker with an existing project written in Kotlin and using Vert.x verticles.
Can you point me to an example on how to deploy verticles using Quarkus?
My dependencies are vertx-sockjs-service-proxy and vertx-lang-kotlin.
I found some examples in the Vert.x extension tests but I cannot find how to deploy my verticles at server startup.
#Inject
EventBus eventBus;
#Route(path = "/hello-event-bus", methods = GET)
void helloEventBus (RoutingExchange exchange){
eventBus.send("hello", exchange.getParam("name").orElse("missing"), ar -> {
if (ar.succeeded()) {
exchange.ok(ar.result().body().toString());
} else {
exchange.serverError().end(ar.cause().getMessage());
}
});
}
You can use verticle as follows:
#Inject Vertx vertx;
void onStart(#Observes StartupEvent ev) {
vertx.deploy(new MyVerticleA());
vertx.deploy(new MyVerticleB());
}
Related
I'm trying to integrate StarMX framework (https://github.com/rogeriogentil/starmx) into a legacy web application. This framework uses JMX techonology and is initialized using the Singleton pattern: StarMXFramework.createInstance(). The web application uses Java EE 6 technologies such as EJB and CDI (also DeltaSpike). However, the way the framework is being initialized (code below) doesn't add its instance to the CDI context.
import org.starmx.StarMXException;
import org.starmx.StarMXFramework;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.Singleton;
import javax.ejb.Startup;
#Startup
#Singleton
public class StarMXSingleton {
private StarMXFramework starMX;
#PostConstruct
public void postConstruct() {
try {
starMX = StarMXFramework.createInstance();
} catch (StarMXException e) {
(...)
}
}
#PreDestroy
public void preDestroy() {
if (starMX != null) {
try {
starMX.shutdown();
} catch (StarMXException e) {
(...)
}
}
}
}
I know that is possible to extend CDI, but is it possible to add an instance of singleton framework to CDI context?
There are two ways, first and easy one is a producer. Here is a link to what CDI producers are and how they work. In short, CDI will use this producer to create the instance of a bean whose types are mandated by the return type of the producer method.
The producer method has to be placed inside a CDI bean so that is it picked up by CDI. Note that the scope of the producer affects how often it will be invoked, just as it would be with standard bean. Here is how it could look like:
#ApplicationScoped
public class SomeCdiBeanInYourApplication {
#Produces //denotes producer method
#ApplicationScoped // scope of produced bean, use CDI scope (the singleton you have is EJB annotation)
public StarMXFramework produceMxFramework() {
return StarMXFramework.createInstance();
}
}
Second means is then CDI extension, namely a lifecycle observer for AfterBeanDiscovery event where you can addBean(). Here is a link to CDI 2.0 spec, feel free to browse older versions based on what version you are on.
I won't write code for that as it is rather complex and long, the producer should do the trick for you.
See also
Please explain the #Produces annotation in CDI
When starting a basic Ktor app, I get:
Exception in thread "main" java.lang.UnsupportedOperationException: Packages and file facades are not yet supported in Kotlin reflection. Meanwhile please use Java reflection to inspect this class: class com.example.ApplicationKt
at kotlin.reflect.jvm.internal.KClassImpl.reportUnresolvedClass(KClassImpl.kt:301)
at kotlin.reflect.jvm.internal.KClassImpl.access$reportUnresolvedClass(KClassImpl.kt:43)
at kotlin.reflect.jvm.internal.KClassImpl$Data$descriptor$2.invoke(KClassImpl.kt:53)
at kotlin.reflect.jvm.internal.KClassImpl$Data$descriptor$2.invoke(KClassImpl.kt:44)
at kotlin.reflect.jvm.internal.ReflectProperties$LazySoftVal.invoke(ReflectProperties.java:92)
at kotlin.reflect.jvm.internal.ReflectProperties$Val.getValue(ReflectProperties.java:31)
at kotlin.reflect.jvm.internal.KClassImpl$Data.getDescriptor(KClassImpl.kt)
at kotlin.reflect.jvm.internal.KClassImpl$Data$objectInstance$2.invoke(KClassImpl.kt:106)
at kotlin.reflect.jvm.internal.ReflectProperties$LazyVal.invoke(ReflectProperties.java:62)
at kotlin.reflect.jvm.internal.ReflectProperties$Val.getValue(ReflectProperties.java:31)
at kotlin.reflect.jvm.internal.KClassImpl$Data.getObjectInstance(KClassImpl.kt)
at kotlin.reflect.jvm.internal.KClassImpl.getObjectInstance(KClassImpl.kt:239)
at io.ktor.server.engine.ApplicationEngineEnvironmentReloading.createModuleContainer(ApplicationEngineEnvironmentReloading.kt:328)
at io.ktor.server.engine.ApplicationEngineEnvironmentReloading.executeModuleFunction(ApplicationEngineEnvironmentReloading.kt:317)
at io.ktor.server.engine.ApplicationEngineEnvironmentReloading.instantiateAndConfigureApplication(ApplicationEngineEnvironmentReloading.kt:275)
at io.ktor.server.engine.ApplicationEngineEnvironmentReloading.createApplication(ApplicationEngineEnvironmentReloading.kt:127)
at io.ktor.server.engine.ApplicationEngineEnvironmentReloading.start(ApplicationEngineEnvironmentReloading.kt:247)
at io.ktor.server.netty.NettyApplicationEngine.start(NettyApplicationEngine.kt:106)
at io.ktor.server.netty.NettyApplicationEngine.start(NettyApplicationEngine.kt:18)
at io.ktor.server.engine.ApplicationEngine$DefaultImpls.start$default(ApplicationEngine.kt:52)
at io.ktor.server.netty.EngineMain.main(EngineMain.kt:17)
at com.example.ApplicationKt.main(Application.kt:10)
The app is just:
fun main(args: Array<String>): Unit = EngineMain.main(args)
fun Application.demoModule() {
routing {
get("/") {
call.respondText("Hello ${call.parameters["name"]}")
}
}
}
I just noticed the file resources.application.conf had an issue.
It had the wrong module name. I changed com.example.ApplicationKt.module to com.example.ApplicationKt.demoModule:
ktor {
deployment {
port = 8080
port = ${?PORT}
}
application {
modules = [ com.example.ApplicationKt.demoModule ]
}
}
What's annoying is that the error help says nothing about it.
I am writing integration tests using Arquillian with embedded glassfish 3.1.2.2 using TestNG. I want to be able to run those tests in parallel, and for this case i need to dynamically configure glassfish ports and database name (we already have this set-up, and I want to reuse it of arquillian tests). What I am missing is a 'before container start' hook, where I could prepare the database, lookup free ports and update my glassfish configuration (domain.xml, could also be glassfish-resources.xml). Is there a 'clean' solution for this, or my usecase was not foreseen by Arquillian developers?
The hacky way I solved it currently is to override arquillian's beforeSuite method but this one gets called twice - at test startup and then in the container (therefore my pathetic static flag). Secondly, this solution would not work for JUnit based tests as there's no way to intercept arquillian's before suite:
public class FullContainerIT extends Arquillian {
private static boolean dbInitialized;
//#RunAsClient <-supported by #Test only
#Override
#BeforeSuite(groups = "arquillian", inheritGroups = true)
public void arquillianBeforeSuite() throws Exception {
if (dbInitialized == false) {
initializeDb();
dbInitialized = true;
}
super.arquillianBeforeSuite();
}
}
Some ideas I had:
+ having #BeforeSuite #RunAsClient seems to be what I need, but #RunAsClient is supported for #Test only;
+ I have seen org.jboss.arquillian.container.spi.event.container.BeforeStart event in Arquillian JavaDocs, but I have no clue how to listen to Arquillian events;
+ I have seen there is a possibility to have #Deployment creating a ShrinkWrap Descriptor, but these do not support Glassfish resources.
I found a clean solution for my problem on JBoss forum. You can register a LoadableExtension SPI and modify the arquillian config (loaded from xml). This is where I can create a database and filter glassfish-resources.xml with proper values. The setup looks like this:
package com.example.extenstion;
public class AutoDiscoverInstanceExtension
implements org.jboss.arquillian.core.spi.LoadableExtension {
#Override
public void register(ExtensionBuilder builder) {
builder.observer(LoadContainerConfiguration.class);
}
}
package com.example.extenstion;
public class LoadContainerConfiguration {
public void registerInstance(#Observes ContainerRegistry, ServiceLoader serviceLoader) {
//Do the necessary setup here
String filteredFilename = doTheFiltering();
//Get the container defined in arquillian.xml and modify it
//"default" is the container's qualifier
Container definition = registry.getContainer("default");
definition.getContainerConfiguration()
.property("resourcesXml", filteredFilename);
}
}
You also need to configure the SPI Extension by creating a file
META-INF/services/org.jboss.arquillian.core.spi.LoadableExtension
with this contents:
com.example.extenstion.AutoDiscoverInstanceExtension
The Swagger documentation covers a number of different ways to configure Swagger in an application. Unfortunately all of them leverage web.xml and rely on hard coding the api version and base url in the web.xml
Is there a way to configure Swagger without using a web.xml and without hardcoding the api version and base path?
I used the following approach to configure Swagger in Glassfish 4 without a resource XML.
Includes the following dependency in by gradle build file (this approach also applies to Maven):
compile ('com.wordnik:swagger-jaxrs_2.9.1:1.3.0') {
exclude group: 'org.scala-lang', module: 'scala-compiler'
}
Create a class that extends javax.ws.rs.core.Application and configure the ApplicationPath e.g.
#ApplicationPath("resources")
public class RESTConfig extends Application {}
2a. Create a class that extends com.wordnik.swagger.jaxrs.config.DefaultJaxrsConfig and annotate as follows:
#WebServlet(name = "SwaagerJaxrsConfig" initParams = {#WebInitParam(name="api.version", value="0.1.0"), #WebInitParam(name="swagger.api.basepath", value="http://localhost:8080/resources"})}, loadOnStartup = 2)
public class SwaagerJaxrsConfig extends DefaultJaxrsConfig{}
The downside of this approach is that the api version and base url of your app is hardcoded in the annotation. In order to get around this I used the following approach instead of the one above
2b. Create a class that extends HttpServlet and performs the bootstrapping done by DefaultJaxrsConfig e.g.
#WebServlet(name = "SwaggerJaxrsConfig", loadOnStartup = 2)
public class SwaggerJaxrsConfig extends HttpServlet {
private Logger log = Logger.getLogger(SwaggerJaxrsConfig.class);
#Inject Version version;
#Override public void init(ServletConfig servletConfig) {
try {
super.init(servletConfig);
SwaggerConfig swaggerConfig = new SwaggerConfig();
ConfigFactory.setConfig(swaggerConfig);
swaggerConfig.setBasePath("http://localhost:8080/resources"); //TODO look up app path
swaggerConfig.setApiVersion(version.getVersion());
ScannerFactory.setScanner(new DefaultJaxrsScanner());
ClassReaders.setReader(new DefaultJaxrsApiReader());
} catch (Exception e) {
log.error("Failed to configure swagger", e);
}
}
}
I'd like to write a test for my ASP.NET WebApi service and run it against a self-hosted service and the live web hosted service. I imagine that this can be done with a test fixture, but I'm not sure how to set it up. Does anyone know of an example of using a configurable test fixture so that you can pass a parameter to Xunit to choose a self hosted fixture or a web hosted fixture?
Here is how it works with latest xUnit 2.0 beta.
Create a fixture:
public class SelfHostFixture : IDisposable {
public static string HostBaseAddress { get; private set; }
HttpSelfHostServer server;
HttpSelfHostConfiguration config;
static SelfHostFixture() {
HostBaseAddress = ConfigurationManager.AppSettings["HostBaseAddress"]; // HttpClient in your tests will need to use same base address
if (!HostBaseAddress.EndsWith("/"))
HostBaseAddress += "/";
}
public SelfHostFixture() {
if (/*your condition to check if running against live*/) {
config = new HttpSelfHostConfiguration(HostBaseAddress);
WebApiConfig.Register(config); // init your web api application
var server = new HttpSelfHostServer(config);
server.OpenAsync().Wait();
}
}
public void Dispose() {
if (server != null) {
server.CloseAsync().Wait();
server.Dispose();
server = null;
config.Dispose();
config = null;
}
}
}
Then define a collection that will use that fixture. Collections are the new concept to group tests in xUnit 2.
[CollectionDefinition("SelfHostCollection")]
public class SelfHostCollection : ICollectionFixture<SelfHostFixture> {}
It serves as just a marker so has no implementation.
Now, mark tests that rely on your host to be in that collection:
[Collection("SelfHostCollection")]
public class MyController1Test {}
[Collection("SelfHostCollection")]
public class MyController4Test {}
The runner will create a single instance of your fixture when running any test from within MyController1Test and MyController4Test ensuring that your server is initiated only once per collection.
I would recommend to use the In-Memory Server for testing your controllers, so you don't need to spin up a self-host in your unit tests.
http://blogs.msdn.com/b/youssefm/archive/2013/01/28/writing-tests-for-an-asp-net-webapi-service.aspx