Initiating a service right after Quarks starts - quarkus

I need to write a piece of code that will run right after quarks is up and running.
Was wondering if such a thing is possible with Quarkus, I tried to do it with a Quarkus main but this only allows me to run the code prior to Quarkus starting.
What is the first module or class that is running when running the below command?
mvn compile quarkus:dev

You can listen to startup and shutdown events, this is the quarkus guide that explains how to do it.
Just quoting this guide:
package org.acme.lifecycle;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.event.Observes;
import io.quarkus.runtime.ShutdownEvent;
import io.quarkus.runtime.StartupEvent;
import org.jboss.logging.Logger;
#ApplicationScoped
public class AppLifecycleBean {
private static final Logger LOGGER = Logger.getLogger("ListenerBean");
void onStart(#Observes StartupEvent ev) {
LOGGER.info("The application is starting...");
}
void onStop(#Observes ShutdownEvent ev) {
LOGGER.info("The application is stopping...");
}
}

Related

Priority of quarkus injections in #QuarkusTest

I have problem with order in integration tests, because I need to load one class before others, but it's currently random.
Is any possibilities to use something that would say to load it first (during running app context) in Quarkus?
I guess it's not possible to order the execution of the Classes in tests. They execute randomly.
I know for sure that you can order the execution of the test methods inside a class.
That said, I used one strategy in one application where I needed to start a process as the first step of my tests.
Inside my test package, I created one class with ApplicationScoped and created one method with the #Observes StartupEvent StartupEvent parameter.
When I execute mvn test, this method is the first to be executed.
Class with a method to start my initializing process
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.event.Observes;
import javax.inject.Inject;
import io.quarkus.runtime.ShutdownEvent;
import io.quarkus.runtime.StartupEvent;
#ApplicationScoped
public class AcceptorStarter {
private static final Logger LOG = LoggerFactory.getLogger(AcceptorStarter.class.getName());
#Inject
AcceptorServer acceptorServer;
// Starts automatically with application
public void onStart(#Observes StartupEvent StartupEvent) {
LOG.info("Starting FIX Acceptor to allow tests");
acceptorServer.init();
}
// Ends automatically with application
public void onStop(#Observes ShutdownEvent shutdownEvent) {
LOG.info("Finishing FIX Acceptor");
acceptorServer.stop();
}
}
Ordering the execution of methods
You can order the execution of the test methods, like this:
import static io.restassured.RestAssured.given;
import javax.inject.Inject;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import io.quarkus.test.junit.QuarkusTest;
#QuarkusTest
#TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class PropertiesRestTest {
#Test
#Order(1)
public void getQuickfixSessionSettings() {
given()
.when()
.get("/properties/quickfix-session-settings")
.then()
.statusCode(200);
}
#Test
#Order(2)
public void putQuickfixSessionSettings() {
given()
.body(appProperties.getQuickfixSessionSettings())
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON)
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON)
.when().put("/properties/quickfix-session-settings")
.then()
.statusCode(200);
}
#Test
#Order(3)
public void restauraQuickfixSessionSettings() {
given()
.when()
.put("/properties/restaura-quickfix-session-settings-original")
.then()
.statusCode(200);
}
}

Why does the Vaadin 20+ server take so long to start the webpack dev server?

Hi I want to update my actual Vaadin 8 Project into a Vaadin 20+ one. I configured under src/main/resources/application.properties the property vaadin.whitelisted-packages=com/mycompany/myproject.
Under src/main/java/com/mycompany/myproject I have a ClientApplication.java class
package com.mycompany.myproject;
import com.vaadin.flow.component.page.AppShellConfigurator;
import com.vaadin.flow.server.PWA;
import com.vaadin.flow.theme.Theme;
/**
* Use the #PWA annotation make the application installable on phones, tablets
* and some desktop browsers.
*/
#Theme(value = "mycompany")
#PWA(name = "My Company Fusion", shortName = "Company Fusion", offlineResources = { "images/logo.png" })
public class ClientApplication implements AppShellConfigurator {
}
Under src/main/java/mycompany/server I have the main Application.java class where the springboot app should start. And Under src/main/java/mycompany I have more than 4K java files which are also important and where I develop actively.
package mycompany.server;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.vaadin.artur.helpers.LaunchUtil;
import mycompany.server.core.MyConfigs;
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
// 1. Load XML config file
final boolean configRead = MyConfigs.readConfig();
if (configRead) {
System.out.println(MyConfigs.getBackendserverurl());
}
// TODO Helmer -> if debug, add prod
ConfigurableApplicationContext ctx = SpringApplication.run(Application.class, args);
LaunchUtil.launchBrowserInDevelopmentMode(ctx);
}
}
Every time I try to run mvn -Dmaven.compiler.failOnError=false -Dmaven.test.skip=true -DskipTests spring-boot:run the webpack server takes more than 10 minutes to start. sometimes it takes more than 30 mins.

Reliable libraries out there for Spring boot redis integration tests

This is more of a question for a tool - googling around I haven't really had much luck.
So basically I have a standard spring boot app - and I have a unit test redis cache configuration. What I am looking to do is run the app context autowire some spring configs and test against a embedded redis cache if possible.
Closest I have come is this https://github.com/kstyrc/embedded-redis.
Problem with that is the lack of robust logging is making it difficult to run - its working locally, but when I push it up, Unix server build machine, its failing and no idea why.
If anyone has any idea of how to run integration tests this way - it would be great.
thanks,
Stefan
I am using embedded-redis for my integration testing with redisson java client.
Here is my dependency
compile group: 'org.redisson', name: 'redisson', version: '3.6.5'
testCompile group: 'it.ozimov', name: 'embedded-redis', version: '0.7.2'
Start embedded redis server before class and stop it in after class.
Redis property:
spring.redis.host=localhost
spring.redis.port=6379
Sample integration test.
import java.util.concurrent.TimeUnit;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.redisson.api.RMap;
import org.redisson.api.RMapCache;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.test.context.junit4.SpringRunner;
import redis.embedded.RedisServer;
#RunWith(SpringRunner.class)
#SpringBootTest(classes = Application.class, webEnvironment = WebEnvironment.RANDOM_PORT)
public class RedisTest {
private static final Logger LOGGER = LoggerFactory.getLogger(RedisTest.class);
private static RedisServer REDISSERVER = new RedisServer(6379);
#LocalServerPort
private int port;
#Autowired
private RedissonClient redissonClient;
#BeforeClass
public static final void before() {
REDISSERVER.start();
}
#AfterClass
public static final void after() {
REDISSERVER.stop();
}
#Test
public void testRedis() throws InterruptedException {
//map
RMap<String, String> map = redissonClient.getMap("user");
map.put("name", "Redis Server");
Assert.assertTrue(map.get("name").equals("Redis Server"));
//mapcache
RMapCache<String, String> mapCache = redissonClient.getMapCache("tempUser");
mapCache.put("name", "Redis Server", 5, TimeUnit.SECONDS);
Assert.assertTrue(mapCache.get("name").equals("Redis Server"));
Thread.sleep(7000); //wait for 7 sec.
Assert.assertTrue(mapCache.get("name") == null);
}
}

How to run DelegatingSecurityContextRunnable every time when tomcat creates new Thread

I have an spring app which is using tomcat with websockets. I would like to use the DelegatingSecurityContextRunnable to be executed every time when tomcat creates a new thread, i.e. warp the tomcat thread. Does anyone know how this is done. The reason for the question can be found.here
Maybe this can be done with using AOP and some advice?
In Spring boot you can configure a Wrapper by hooking into the Tomcat connector. See this as an example:
#Bean
public EmbeddedServletContainerFactory servletContainerFactory() {
TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();
factory.addConnectorCustomizers(new TomcatConnectorCustomizer() {
#Override
public void customize(Connector connector) {
AbstractProtocol protocolHandler = (AbstractProtocol) connector.getProtocolHandler();
TaskQueue taskqueue = new TaskQueue() {
#Override
public boolean offer(Runnable e, long timeout, TimeUnit unit) throws InterruptedException {
return super.offer(new MyRunnable(e), timeout, unit);
}
#Override
public boolean offer(Runnable o) {
return super.offer(new MyRunnable(o));
}
};
TaskThreadFactory tf = new TaskThreadFactory("artur-" + "-exec-", false, 0);
ThreadPoolExecutor e = new ThreadPoolExecutor(10, 10, 1000, TimeUnit.SECONDS, taskqueue);
taskqueue.setParent(e);
protocolHandler.setExecutor(e);
}
});
return factory;
}
And here is my custom Runable (this can be any wrapper, i did not bother implementing exactly yours):
static class MyRunnable implements Runnable {
private Runnable r;
public MyRunnable(Runnable r) {
this.r = r;
}
#Override
public void run() {
System.out.println("Custom runable");
runInner();
}
void runInner() {
r.run();
}
}
And here are my imports:
import java.util.concurrent.TimeUnit;
import org.apache.catalina.connector.Connector;
import org.apache.coyote.AbstractProtocol;
import org.apache.tomcat.util.threads.TaskQueue;
import org.apache.tomcat.util.threads.TaskThreadFactory;
import org.apache.tomcat.util.threads.ThreadPoolExecutor;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.boot.web.support.SpringBootServletInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.PropertySource;
What this does:
The Tomcat connector initialises itself. You can set the executor to use, in which case Tomcat will stop creating its own configuration and instead use yours.
By overwriting the offer methods in the queue, you have the chance to wrap your Runnable in any custom Runnable. In my case, for testing, I simply added a Sysout to see that everything is working correctly.
The Threadpool implementation I used is an exact copy of the tomcat default (minus the properties). This way, behaviour stays the same, except that any Runnable is now your delegating wrapper.
When I test that, my console prints:
Custom runable
I hope this is what you were looking for.
I use spring boot, but this is essentially a tomcat issue not a spring issue. You can adapt the solution to your specific scenario.
-- Artur

how to use the ApplicationArguments in spring-boot

I am learning the Spring-Boot(I am new to it), reading the Spring Boot Document. In the 23.6 Accessing application arguments, It talk about the ApplicationArguments, and the code is:
package com.example.project;
import org.springframework.boot.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.stereotype.*;
import java.util.*;
#Component
public class MyBean {
#Autowired
public MyBean(ApplicationArguments args) {
boolean debug = args.containsOption("debug");
List<String> files = args.getNonOptionArgs();
System.out.println(debug);
System.out.println(files);
}
}
It says if run with "--debug logfile.txt" debug=true, files=["logfile.txt"].
But in my project, I don't know how to run it. I create the spring-boot using Maven: The Project Structure
In Spring Boot doc ApplicationArguments is autowired in a bean. Here is a more hands on example where it's used in a Main method.
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class Application implements ApplicationRunner {
public static void main(String[] args) {
SpringApplication.run(Application.class, args).stop();
}
#Override
public void run(ApplicationArguments args) throws Exception {
boolean debug = args.containsOption("debug");
List<String> files = args.getNonOptionArgs();
System.out.println(debug);
System.out.println(files);
}
}
Assuming that you have an Application class with annotation #SpringBootApplication like in the answer provided by a.b.d.
To be able to provide the arguments within IntelliJ IDEA environment you will need to first Run the main method and then Edit 'Run/Debug Configurations' and under Main Class fill Program arguments field with "--debug logfile.txt":
In one word like a thousand :
the 'Program arguments' in your IDE field prefixed by -- is simply the same name as the 'Option' expected in the 'ApplicationArguments'.
Hence you can match --debug and "args.containsOption("debug")".

Resources