Intelij IDEA 2022.1 Cannot debug Runtime.getRuntime().addShutdownHook(); - java

I've tried to debug Runtime.getRuntime().addShutdownHook(unfortunateHook); in sample tapestry application created with Maven quickstart, but it seems that it doesn't work - Debugger doesn't stop at trap set to line set at LOGGER.debug("In the main hook!!!");
Example code:
package org.example.spring;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
#SpringBootApplication
public class App extends SpringBootServletInitializer {
private static final Logger LOGGER= LoggerFactory.getLogger(App.class);
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(AppConfiguration.class);
}
public static void main(String[] args) throws Exception {
Thread unfortunateHook = new Thread(() -> {
LOGGER.debug("In the main hook!!!");
try
{
Thread.sleep(5000);
}
catch (InterruptedException e)
{
throw new RuntimeException(e);
}
});
Runtime.getRuntime().addShutdownHook(unfortunateHook);
LOGGER.debug("Simple log statement with inputs {}, {} and {}", 1,2,3);
SpringApplication application = new SpringApplication(App.class);
SpringApplication.run(App.class, args);
}
}
Is it possible to debug code inside shutdown hook thread? I'm using InteliJ Idea 2022.01. Killing application with standard Intelij Idea way (red square).

Ok, after some more digging I have found this: https://youtrack.jetbrains.com/issue/IDEA-170313/Breakpoints-not-working-after-stop-signal and many more simmilar threads.
In short, Idea is disconnecting debugger in a moment that you click red square and sends signal to app to kill itself. Because of these, traps are not working any more.
Workaround to this is to send kill signal from external source. In Linux it's pretty easy but in windows (which is I'm using) you should:
Put a break point any place in your code that will be executed
When code stops at your trap, you go to "evaulate expression" (alt+f8 or from degug acctions) and write System.exit(0)
You breakpoint may need to be set up as a thread one - to do that, click right button on it and switch to "Thread"
Then breakpoint should work.

Related

How to start multiple message consumers in Quarkus?

I'm trying to migrate from Vert.x to Quarkus and in Vert.x when I write message consumers like Kafka/AMQP etc. I have to scale the number of verticals to maximize performance across multiple cores i.e. Vertical Scaling - is this possible in Quarkus? I see a similar question here but it wasn't answered.
For example, with Kafka I might create a consumer inside a vertical and then scale that vertical say 10 times (that is specify the number of instances in the deployment to be 10) after doing performance testing to determine that's the optimal number. My understanding is that by default, 1 vertical = 1 event loop and does not scale across multiple cores.
I know that it's possible to use Vert.x verticals in Quarkus but is there another way to scale things like the number of Kafka consumers across multiple core?
I see that this type of scalability is configurable for things like Quarkus HTTP but I can't find anything about message consumers.
Here's the Vert.x Verticle approach that overall I'm very happy with, but I wish there were better documentation on how to do this.
UPDATE - Field injection doesn't work with this example but constructor injection does work.
Lets say I want to inject this
#ApplicationScoped
public class CoffeeRepositoryService {
public CoffeeRepositoryService() {
System.out.println("Injection succeeded!");
}
}
Here's my Verticle
package org.acme;
import io.smallrye.mutiny.Uni;
import io.smallrye.mutiny.vertx.core.AbstractVerticle;
import io.vertx.core.impl.logging.Logger;
import io.vertx.core.impl.logging.LoggerFactory;
import io.vertx.mutiny.core.eventbus.EventBus;
import io.vertx.mutiny.rabbitmq.RabbitMQClient;
import io.vertx.mutiny.rabbitmq.RabbitMQConsumer;
import io.vertx.rabbitmq.QueueOptions;
import io.vertx.rabbitmq.RabbitMQOptions;
public class RQVerticle extends AbstractVerticle {
private final Logger LOGGER = LoggerFactory.getLogger(org.acme.RQVerticle.class);
//This doesn't work - returns null
#Inject
CoffeeRepositoryService coffeeRepositoryService;
RQVerticle() {} // dummy constructor needed
#Inject // constructor injection - this does work
RQVerticle(CoffeeRepositoryService coffeeRepositoryService) {
//Here coffeeRepositoryService is injected properly
}
#Override
public Uni<Void> asyncStart() {
LOGGER.info(
"Creating RabbitMQ Connection after Quarkus successful initialization");
RabbitMQOptions config = new RabbitMQOptions();
config.setUri("amqp://localhost:5672");
RabbitMQClient client = RabbitMQClient.create(vertx, config);
Uni<Void> clientResp = client.start();
clientResp.subscribe()
.with(asyncResult -> {
LOGGER.info("RabbitMQ successfully connected!");
});
return clientResp;
}
}
Main Class - injection doesn't work like this
package org.acme;
import io.quarkus.runtime.Quarkus;
import io.quarkus.runtime.QuarkusApplication;
import io.quarkus.runtime.annotations.QuarkusMain;
import io.vertx.core.DeploymentOptions;
import io.vertx.mutiny.core.Vertx;
#QuarkusMain
public class Main {
public static void main(String... args) {
Quarkus.run(MyApp.class, args);
}
public static class MyApp implements QuarkusApplication {
#Override
public int run(String... args) throws Exception {
var vertx = Vertx.vertx();
System.out.println("Deployment Starting");
DeploymentOptions options = new DeploymentOptions()
.setInstances(2);
vertx.deployVerticleAndAwait(RQVerticle::new, options);
System.out.println("Deployment completed");
Quarkus.waitForExit();
return 0;
}
}
}
Main Class with working injection but cannot deploy more than one instance
package org.acme;
import io.quarkus.runtime.StartupEvent;
import io.vertx.mutiny.core.Vertx;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.event.Observes;
import org.jboss.logging.Logger;
#ApplicationScoped
public class MainVerticles {
private static final Logger LOGGER = Logger.getLogger(MainVerticles.class);
public void init(#Observes StartupEvent e, Vertx vertx, RQVerticle verticle) {
public void init(#Observes StartupEvent e, Vertx vertx, RQVerticle verticle) {
DeploymentOptions options = new DeploymentOptions()
.setInstances(2);
vertx.deployVerticle(verticle,options).await().indefinitely();
}
}
Std Out - first main class looks good
2021-09-15 15:48:12,052 INFO [org.acm.RQVerticle] (vert.x-eventloop-thread-2) Creating RabbitMQ Connection after Quarkus successful initialization
2021-09-15 15:48:12,053 INFO [org.acm.RQVerticle] (vert.x-eventloop-thread-3) Creating RabbitMQ Connection after Quarkus successful initialization
Std Out - second main class
2021-09-22 15:48:11,986 ERROR [io.qua.run.Application] (Quarkus Main
Thread) Failed to start application (with profile dev):
java.lang.IllegalArgumentException: Can't specify > 1 instances for
already created verticle

Alternative to setSubscriber in Esper

I am trying to attach a subscriber to an event in Esper but I would like to use .epl file for that. I've been browsing repositories and I have seen examples of doing that by using annotation interfaces. I was trying to do it the same way they do it in CoinTrader, but I can't seem to get it to work. Yet, if I set the subscriber in Java, it works.
This is my project structure for reference
This is my .epl file:
module queries;
import events.*;
import configDemo.*;
import annotations.*;
create schema MyTickEvent as TickEvent;
#Name('allEvents')
#Description('test')
#Subscriber(className='configDemo.TickSubscriber')
select * from TickEvent;
#Name('tickEvent')
#Description('Get a tick event every 3 seconds')
select currentPrice from TickEvent;
This is my config file:
<?xml version="1.0" encoding="UTF-8"?>
<esper-configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.espertech.com/schema/esper"
xsi:noNamespaceSchemaLocation="esper-configuration-6-0.xsd">
<event-type-auto-name package-name="events"/>
<auto-import import-name="annotations.*"/>
<auto-import import-name="events.*"/>
<auto-import import-name="configDemo.*"/>
This is my Subscriber interface:
package annotations;
public #interface Subscriber {
String className();
}
This is my event class:
package configDemo;
import events.TickEvent;
public class TickSubscriber {
public void update(TickEvent tick) {
System.out.println("Event registered by subscriber - Tick is: " +
tick.getCurrentPrice());
}
}
And my main file is this:
package configDemo;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import com.espertech.esper.client.EPStatement;
import com.espertech.esper.client.deploy.DeploymentException;
import com.espertech.esper.client.deploy.DeploymentOptions;
import com.espertech.esper.client.deploy.Module;
import com.espertech.esper.client.deploy.ParseException;
public class Main {
public static EngineHelper engineHelper;
public static Thread engineThread;
public static boolean continuousSimulation = true;
public static void main(String[] args) throws DeploymentException, InterruptedException, IOException, ParseException {
engineHelper = new EngineHelper();
DeploymentOptions options = new DeploymentOptions();
options.setIsolatedServiceProvider("validation"); // we isolate any statements
options.setValidateOnly(true); // validate leaving no started statements
options.setFailFast(false); // do not fail on first error
Module queries = engineHelper.getDeployAdmin().read("queries.epl");
engineHelper.getDeployAdmin().deploy(queries, null);
CountDownLatch latch = new CountDownLatch(1);
EPStatement epl = engineHelper.getAdmin().getStatement("allEvents");
//epl.setSubscriber(new TickSubscriber());
engineThread = new Thread(new EngineThread(latch, continuousSimulation, engineHelper.getRuntime()));
engineThread.start();
}
}
As you can see the setSubscriber line is commented out. When I run it as is, I expected that the subscriber will be recognized and registered and yet it isn't. I only get the tick events flowing in the console. If I decomment the line and I run it, I get a notification after each tick that the subscriber received the event and it all works fine.
What am I doing wrong? How can I set a subscriber within the .epl file?
Assigning a subscriber is done by the application and is not something that the engine does for you. The app code would need to loop thru the statements, get the annotations "stmt.getAnnotations" and inspect these and assign the subscriber.

Shutdown hooks in Spring

I am trying to add a shutdown hook via Runtime.getRuntime().addShutdownHook() in a Spring Gradle application.
I tried adding an anonymous thread subclass to the Application.java class from this exact tutorial So that it looks like this:
package hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class Application {
public static void main(String[] args) {
Thread thread = new Thread() {
public void run() {
System.out.println("Shutdown Thread!");
}
};
Runtime.getRuntime().addShutdownHook(thread);
SpringApplication.run(Application.class, args);
}
}
However, I am not seeing the desired behavior: printing "Shutdown Thread!" on exiting the application. What is going wrong here?
edit: I have been shutting it down using control + c on the terminal where it is running. I am running it on the OSX terminal

Boolean wont Update from Object.getBoolean();

Pretty much, I'm trying to write a simple program that lets the user choose a file. Unfortunately, JFileChooser through Swing is a little outdated, so I am trying to use JavaFX FileChooser for this. The goal is to run FileGetter as a thread, transfer the file data to the Main Class, and continue from there.
Main Class:
package application;
import java.io.File;
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
public class Main {
public static void main(String[] args) {
Thread t1 = new Thread(new FileGetter());
FileGetter fg = new FileGetter();
t1.start();
boolean isReady = false;
while(isReady == false){
isReady = FileGetter.getIsReady();
}
File file = FileGetter.getFile();
System.out.println(file.getAbsolutePath());
...
}
}
FileGetter Class:
package application;
import java.io.File;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
public class FileGetter extends Application implements Runnable {
static File file;
static boolean isReady = false;
#Override
public void start(Stage primaryStage) {
try {
FileChooser fc = new FileChooser();
while(file == null){
file = fc.showOpenDialog(primaryStage);
}
isReady = true;
Platform.exit();
} catch(Exception e) {
e.printStackTrace();
}
}
#Override
public void run() {
launch();
}
public static boolean getIsReady(){
return isReady;
}
public static File getFile(){
return file;
}
}
Problem is that the value of isReady in the while loop doesn't update to true when the user picked a file (the reason I have it is to prevent the code in Main from continuing with a File set to null).
Any help, alternative suggestions, or explanations as of why this happens is very much appreciated!
The java memory model does not require variable values to be the same in different threads except under specific conditions.
What is happening here is that the FileGetter thread is updating the value in the own memory that is only accessed from this thread, but your main thread doesn't see the updated value, since it only sees the version of the variable stored in it's own memory that is different from the one of the FileGetter thread. Each of the threads has it's own copy of the field in memory, which is perfectly fine according to the java specification.
To fix this, you can simply add the volatile modifier to isReady:
static volatile boolean isReady = false;
which makes sure the updated value will be visible from your main thread.
Furthermore I recommend reducing the number of FileGetter instances you create. In your code 3 instances are created, but only 1 is used.
Thread t1 = new Thread(() -> Application.launch(FileGetter.class));
t1.start();
...
The easiest way to implement this
Instead of trying to drive the horse with the cart, why not just follow the standard JavaFX lifecycle? In other words, make your Main class a subclass of Application, get the file in the start() method, and then proceed (in a background thread) with the rest of the application?
public class Main extends Application {
#Override
public void init() {
// make sure we don't exit when file chooser is closed...
Platform.setImplicitExit(false);
}
#Override
public void start(Stage primaryStage) {
File file = null ;
FileChooser fc = new FileChooser();
while(file == null){
file = fc.showOpenDialog(primaryStage);
}
final File theFile = file ;
new Thread(() -> runApplication(theFile)).start();
}
private void runApplication(File file) {
// run your application here...
}
}
What is wrong with your code
If you really want the Main class to be separate from the JavaFX Application class (which doesn't really make sense: once you have decided to use a JavaFX FileChooser, you have decided you are writing a JavaFX application, so the startup class should be a subclass of Application), then it gets a bit tricky. There are several issues with your code as it stands, some of which are addressed in other answers. The main issue, as shown in Fabian's answer, is that you are referencing FileGetter.isReady from multiple threads without ensuring liveness. This is exactly the issue addressed in Josh Bloch's Effective Java (Item 66 in the 2nd edition).
Another issue with your code is that you won't be able to use the FileGetter more than once (you can't call launch() more than once), which might not be an issue in your code now, but almost certainly will be at some point with this application as development progresses. The problem is that you have mixed two issues: starting the FX toolkit, and retrieving a File from a FileChooser. The first thing must only be done once; the second should be written to be reusable.
And finally your loop
while(isReady == false){
isReady = FileGetter.getIsReady();
}
is very bad practice: it checks the isReady flag as fast as it possibly can. Under some (fairly unusual) circumstances, it could even prevent the FX Application thread from having any resources to run. This should just block until the file is ready.
How to fix without making Main a JavaFX Application
So, again only if you have a really pressing need to do so, I would first create a class that just has the responsibility of starting the FX toolkit. Something like:
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.stage.Stage;
public class FXStarter extends Application {
private static final AtomicBoolean startRequested = new AtomicBoolean(false);
private static final CountDownLatch latch = new CountDownLatch(1);
#Override
public void init() {
Platform.setImplicitExit(false);
}
#Override
public void start(Stage primaryStage) {
latch.countDown();
}
/** Starts the FX toolkit, if not already started via this method,
** and blocks execution until it is running.
**/
public static void startFXIfNeeded() throws InterruptedException {
if (! startRequested.getAndSet(true)) {
new Thread(Application::launch).start();
}
latch.await();
}
}
Now create a class that gets a file for you. This should ensure the FX toolkit is running, using the previous class. This implementation allows you to call getFile() from any thread:
import java.io.File;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import javafx.application.Platform;
import javafx.stage.FileChooser;
public class FileGetter {
/**
** Retrieves a file from a JavaFX File chooser. This method can
** be called from any thread, and will block until the user chooses
** a file.
**/
public File getFile() throws InterruptedException {
FXStarter.startFXIfNeeded() ;
if (Platform.isFxApplicationThread()) {
return doGetFile();
} else {
FutureTask<File> task = new FutureTask<File>(this::doGetFile);
Platform.runLater(task);
try {
return task.get();
} catch (ExecutionException exc) {
throw new RuntimeException(exc);
}
}
}
private File doGetFile() {
File file = null ;
FileChooser chooser = new FileChooser() ;
while (file == null) {
file = chooser.showOpenDialog(null) ;
}
return file ;
}
}
and finally your Main is just
import java.io.File;
public class Main {
public static void main(String[] args) throws InterruptedException {
File file = new FileGetter().getFile();
// proceed...
}
}
Again, this is pretty complex; I see no reason not to simply use the standard FX Application lifecycle for this, as in the very first code block in the answer.
In this code
while(isReady == false){
isReady = FileGetter.getIsReady();
}
there is nothing that is going to change the state of FileGetter's isReady to true

How to do remote JNLP error reporting?

I have a JNLP downloader application deployed on remote user machines that downloads files.
I need to get some error feedback mailed to me. Not so much exceptions, just things getting stuck, or stalled or in infinite loops.
Currently I have a basic handler:
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
public class javaerrorlog {
private static Logger l = Logger.getLogger("");
public static void main(String args[]) throws Exception{
FileHandler handler = new FileHandler("log.txt");
l.addHandler(handler);
l.setLevel(Level.ALL);
l.info("Error logs");
try {
} catch (Error ex) {
l.log(Level.INFO, "", ex);
}
l.fine("");
}
}
Also, should I prompt for the client's permission to send error reporting data?
If you just need notifications you could use something like SMTPHandler. If you need it more fancy you could use JMS with an MDB.

Categories

Resources