Skip to content

Commit

Permalink
Merge branch 'main' into up-port-qe-fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
rolfedh authored Jul 10, 2024
2 parents 999e386 + 389f694 commit 2a21bec
Show file tree
Hide file tree
Showing 42 changed files with 972 additions and 217 deletions.
3 changes: 3 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,9 @@ If you have not done so on this machine, you need to:
* macOS: Use the `Disk Utility.app` to check. It also allows you to create a case-sensitive volume to store your code projects. See this [blog entry](https://karnsonline.com/case-sensitive-apfs/) for more.
* Windows: [Enable case sensitive file names per directory](https://learn.microsoft.com/en-us/windows/wsl/case-sensitivity)
* Install Git and configure your GitHub access
* Windows:
* enable longpaths: `git config --global core.longpaths true`
* avoid CRLF breaks: `git config --global core.autocrlf false`
* Install Java SDK 17+ (OpenJDK recommended)
* Install [GraalVM](https://quarkus.io/guides/building-native-image)
* Install platform C developer tools:
Expand Down
2 changes: 1 addition & 1 deletion build-parent/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@

<unboundid-ldap.version>7.0.1</unboundid-ldap.version>

<assertj.version>3.26.0</assertj.version>
<assertj.version>3.26.3</assertj.version>

<wiremock.version>3.8.0</wiremock.version>
<wiremock-maven-plugin.version>7.3.0</wiremock-maven-plugin.version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@

import io.quarkus.builder.item.MultiBuildItem;

/**
* Transform a class using ASM {@link ClassVisitor}. Note that the transformation is performed after assembling the
* index and thus the changes won't be visible to any processor steps relying on the index.
* <p>
* You may consider using {@code io.quarkus.arc.deployment.AnnotationsTransformerBuildItem} if your transformation
* should be visible for Arc. See also
* <a href="https://quarkus.io/version/main/guides/cdi-integration#annotations_transformer_build_item">I Need To
* Transform Annotation Metadata</a> section of Quarkus CDI integration guide.
*/
public final class BytecodeTransformerBuildItem extends MultiBuildItem {

final String classToTransform;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public class DevModeMain implements Closeable {

private final DevModeContext context;

private static volatile CuratedApplication curatedApplication;
private volatile CuratedApplication curatedApplication;
private Closeable realCloseable;

public DevModeMain(DevModeContext context) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import java.util.ServiceLoader;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
Expand Down Expand Up @@ -61,16 +62,16 @@ public class IsolatedDevModeMain implements BiConsumer<CuratedApplication, Map<S
private volatile DevModeContext context;

private final List<HotReplacementSetup> hotReplacementSetups = new ArrayList<>();
private static volatile RunningQuarkusApplication runner;
static volatile Throwable deploymentProblem;
private static volatile CuratedApplication curatedApplication;
private static volatile AugmentAction augmentAction;
private static volatile boolean restarting;
private static volatile boolean firstStartCompleted;
private static final CountDownLatch shutdownLatch = new CountDownLatch(1);
private volatile RunningQuarkusApplication runner;
final AtomicReference<Throwable> deploymentProblem = new AtomicReference<>();
private volatile CuratedApplication curatedApplication;
private volatile AugmentAction augmentAction;
private volatile boolean restarting;
private volatile boolean firstStartCompleted;
private final CountDownLatch shutdownLatch = new CountDownLatch(1);
private Thread shutdownThread;
private CodeGenWatcher codeGenWatcher;
private static volatile ConsoleStateManager.ConsoleContext consoleContext;
private volatile ConsoleStateManager.ConsoleContext consoleContext;
private final List<DevModeListener> listeners = new ArrayList<>();

private synchronized void firstStart() {
Expand All @@ -85,30 +86,7 @@ private synchronized void firstStart() {
//TODO: look at implementing a common core classloader, that removes the need for this sort of crappy hack
curatedApplication.getOrCreateBaseRuntimeClassLoader().loadClass(ApplicationLifecycleManager.class.getName())
.getMethod("setDefaultExitCodeHandler", Consumer.class)
.invoke(null, new Consumer<Integer>() {
@Override
public void accept(Integer integer) {
if (restarting || ApplicationLifecycleManager.isVmShuttingDown()
|| context.isAbortOnFailedStart() ||
context.isTest()) {
return;
}
if (consoleContext == null) {
consoleContext = ConsoleStateManager.INSTANCE
.createContext("Completed Application");
}
//this sucks, but when we get here logging is gone
//so we just setup basic console logging
InitialConfigurator.DELAYED_HANDLER.addHandler(new ConsoleHandler(
ConsoleHandler.Target.SYSTEM_OUT,
new ColorPatternFormatter("%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c{3.}] (%t) %s%e%n")));
consoleContext.reset(new ConsoleCommand(' ', "Restarts the application", "to restart", 0, null,
() -> {
consoleContext.reset();
RuntimeUpdatesProcessor.INSTANCE.doScan(true, true);
}));
}
});
.invoke(null, getExitCodeHandler());

StartupAction start = augmentAction.createInitialRuntimeApplication();

Expand All @@ -127,7 +105,7 @@ public void accept(Integer integer) {
rootCause = rootCause.getCause();
}
if (!(rootCause instanceof BindException)) {
deploymentProblem = t;
deploymentProblem.set(t);
if (!context.isAbortOnFailedStart()) {
//we need to set this here, while we still have the correct TCCL
//this is so the config is still valid, and we can read HTTP config from application.properties
Expand Down Expand Up @@ -174,6 +152,35 @@ public void accept(Integer integer) {
}
}

private Consumer<Integer> getExitCodeHandler() {
if (context.isTest() || context.isAbortOnFailedStart()) {
return TestExitCodeHandler.INSTANCE;
}

return new Consumer<Integer>() {
@Override
public void accept(Integer integer) {
if (restarting || ApplicationLifecycleManager.isVmShuttingDown()) {
return;
}
if (consoleContext == null) {
consoleContext = ConsoleStateManager.INSTANCE
.createContext("Completed Application");
}
//this sucks, but when we get here logging is gone
//so we just setup basic console logging
InitialConfigurator.DELAYED_HANDLER.addHandler(new ConsoleHandler(
ConsoleHandler.Target.SYSTEM_OUT,
new ColorPatternFormatter("%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c{3.}] (%t) %s%e%n")));
consoleContext.reset(new ConsoleCommand(' ', "Restarts the application", "to restart", 0, null,
() -> {
consoleContext.reset();
RuntimeUpdatesProcessor.INSTANCE.doScan(true, true);
}));
}
};
}

public void restartCallback(Set<String> changedResources, ClassScanResult result) {
restartApp(changedResources,
new ClassChangeInformation(result.changedClassNames, result.deletedClassNames, result.addedClassNames));
Expand All @@ -186,7 +193,7 @@ public synchronized void restartApp(Set<String> changedResources, ClassChangeInf
}
stop();
Timing.restart(curatedApplication.getOrCreateAugmentClassLoader());
deploymentProblem = null;
deploymentProblem.set(null);
ClassLoader old = Thread.currentThread().getContextClassLoader();
try {

Expand All @@ -200,7 +207,7 @@ public synchronized void restartApp(Set<String> changedResources, ClassChangeInf
firstStartCompleted = true;
}
} catch (Throwable t) {
deploymentProblem = t;
deploymentProblem.set(t);
Throwable rootCause = t;
while (rootCause.getCause() != null) {
rootCause = rootCause.getCause();
Expand Down Expand Up @@ -253,7 +260,7 @@ private RuntimeUpdatesProcessor setupRuntimeCompilation(DevModeContext context,
public byte[] apply(String s, byte[] bytes) {
return ClassTransformingBuildStep.transform(s, bytes);
}
}, testSupport);
}, testSupport, deploymentProblem);

for (HotReplacementSetup service : ServiceLoader.load(HotReplacementSetup.class,
curatedApplication.getOrCreateBaseRuntimeClassLoader())) {
Expand Down Expand Up @@ -350,6 +357,7 @@ public void close() {
curatedApplication.close();
curatedApplication = null;
augmentAction = null;
deploymentProblem.set(null);
} finally {
if (shutdownThread != null) {
try {
Expand Down Expand Up @@ -422,10 +430,11 @@ public void run() {
firstStart();

// doStart(false, Collections.emptySet());
if (deploymentProblem != null || RuntimeUpdatesProcessor.INSTANCE.getCompileProblem() != null) {
if (deploymentProblem.get() != null || RuntimeUpdatesProcessor.INSTANCE.getCompileProblem() != null) {
if (context.isAbortOnFailedStart()) {
Throwable throwable = deploymentProblem == null ? RuntimeUpdatesProcessor.INSTANCE.getCompileProblem()
: deploymentProblem;
Throwable throwable = deploymentProblem.get() == null
? RuntimeUpdatesProcessor.INSTANCE.getCompileProblem()
: deploymentProblem.get();

throw (throwable instanceof RuntimeException ? (RuntimeException) throwable
: new RuntimeException(throwable));
Expand Down Expand Up @@ -483,4 +492,14 @@ public boolean test(String s) {
}).produces(ApplicationClassPredicateBuildItem.class).build();
}
}

private static class TestExitCodeHandler implements Consumer<Integer> {

private static final TestExitCodeHandler INSTANCE = new TestExitCodeHandler();

@Override
public void accept(Integer exitCode) {
// do nothing
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.util.Optional;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Function;
Expand Down Expand Up @@ -57,7 +58,7 @@ public class IsolatedRemoteDevModeMain implements BiConsumer<CuratedApplication,
private volatile DevModeContext context;

private final List<HotReplacementSetup> hotReplacementSetups = new ArrayList<>();
static volatile Throwable deploymentProblem;
private AtomicReference<Throwable> deploymentProblem = new AtomicReference<>();
static volatile RemoteDevClient remoteDevClient;
static volatile Closeable remoteDevClientSession;
private static volatile CuratedApplication curatedApplication;
Expand Down Expand Up @@ -99,7 +100,7 @@ private synchronized JarResult generateApplication() {
curatedApplication.getApplicationModel(), null);
return start.getJar();
} catch (Throwable t) {
deploymentProblem = t;
deploymentProblem.set(t);
log.error("Failed to generate Quarkus application", t);
return null;
}
Expand Down Expand Up @@ -137,7 +138,7 @@ public void accept(DevModeContext.ModuleInfo moduleInfo, String s) {
public byte[] apply(String s, byte[] bytes) {
return ClassTransformingBuildStep.transform(s, bytes);
}
}, null);
}, null, deploymentProblem);

for (HotReplacementSetup service : ServiceLoader.load(HotReplacementSetup.class,
curatedApplication.getOrCreateBaseRuntimeClassLoader())) {
Expand Down Expand Up @@ -189,6 +190,7 @@ public void close() {
}
}
} finally {
deploymentProblem.set(null);
curatedApplication.close();
}

Expand Down Expand Up @@ -248,7 +250,7 @@ public void run() {
}

private Closeable doConnect() {
return remoteDevClient.sendConnectRequest(new RemoteDevState(currentHashes, deploymentProblem),
return remoteDevClient.sendConnectRequest(new RemoteDevState(currentHashes, deploymentProblem.get()),
new Function<Set<String>, Map<String, byte[]>>() {
@Override
public Map<String, byte[]> apply(Set<String> fileNames) {
Expand Down Expand Up @@ -283,6 +285,7 @@ private RemoteDevClient.SyncResult runSync() {
Set<String> removed = new HashSet<>();
Map<String, byte[]> changed = new HashMap<>();
try {
deploymentProblem.set(null);
boolean scanResult = RuntimeUpdatesProcessor.INSTANCE.doScan(true);
if (!scanResult && !copiedStaticResources.isEmpty()) {
scanResult = true;
Expand All @@ -305,7 +308,7 @@ private RemoteDevClient.SyncResult runSync() {
currentHashes = newHashes;
}
} catch (IOException e) {
deploymentProblem = e;
deploymentProblem.set(e);
}
return new RemoteDevClient.SyncResult() {
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ public class IsolatedTestModeMain extends IsolatedDevModeMain {
private volatile DevModeContext context;

private final List<HotReplacementSetup> hotReplacementSetups = new ArrayList<>();
static volatile Throwable deploymentProblem;
private static volatile CuratedApplication curatedApplication;
private static volatile AugmentAction augmentAction;

Expand Down Expand Up @@ -68,7 +67,7 @@ public void accept(DevModeContext.ModuleInfo moduleInfo, String s) {
public byte[] apply(String s, byte[] bytes) {
return ClassTransformingBuildStep.transform(s, bytes);
}
}, testSupport);
}, testSupport, deploymentProblem);

for (HotReplacementSetup service : ServiceLoader.load(HotReplacementSetup.class,
curatedApplication.getOrCreateBaseRuntimeClassLoader())) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.BiConsumer;
Expand Down Expand Up @@ -91,6 +92,7 @@ public class RuntimeUpdatesProcessor implements HotReplacementContext, Closeable
volatile Throwable compileProblem;
volatile Throwable testCompileProblem;
volatile Throwable hotReloadProblem;
private final AtomicReference<Throwable> deploymentProblem;

private volatile Predicate<ClassInfo> disableInstrumentationForClassPredicate = new AlwaysFalsePredicate<>();
private volatile Predicate<Index> disableInstrumentationForIndexPredicate = new AlwaysFalsePredicate<>();
Expand Down Expand Up @@ -141,7 +143,7 @@ public RuntimeUpdatesProcessor(Path applicationRoot, DevModeContext context, Qua
DevModeType devModeType, BiConsumer<Set<String>, ClassScanResult> restartCallback,
BiConsumer<DevModeContext.ModuleInfo, String> copyResourceNotification,
BiFunction<String, byte[], byte[]> classTransformers,
TestSupport testSupport) {
TestSupport testSupport, AtomicReference<Throwable> deploymentProblem) {
this.applicationRoot = applicationRoot;
this.context = context;
this.compiler = compiler;
Expand Down Expand Up @@ -180,6 +182,7 @@ public void testsDisabled() {
}
});
}
this.deploymentProblem = deploymentProblem;
}

public TestSupport getTestSupport() {
Expand Down Expand Up @@ -392,7 +395,7 @@ public List<Path> getResourcesDir() {
public Throwable getDeploymentProblem() {
//we differentiate between these internally, however for the error reporting they are the same
return compileProblem != null ? compileProblem
: IsolatedDevModeMain.deploymentProblem != null ? IsolatedDevModeMain.deploymentProblem
: deploymentProblem.get() != null ? deploymentProblem.get()
: hotReloadProblem;
}

Expand Down Expand Up @@ -535,7 +538,7 @@ public boolean doScan(boolean userInitiated, boolean forceRestart) {
//all broken we just assume the reason that they have refreshed is because they have fixed something
//trying to watch all resource files is complex and this is likely a good enough solution for what is already an edge case
boolean restartNeeded = !instrumentationChange && (changedClassResults.isChanged()
|| (IsolatedDevModeMain.deploymentProblem != null && userInitiated) || fileRestartNeeded);
|| (deploymentProblem.get() != null && userInitiated) || fileRestartNeeded);
if (restartNeeded) {
String changeString = changedFilesForRestart.stream().map(Path::getFileName).map(Object::toString)
.collect(Collectors.joining(", "));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ public static void run(Application application, Class<? extends QuarkusApplicati
if (!alreadyStarted) {
application.stop(); //this could have already been called
}
currentApplication = null;
(exitCodeHandler == null ? defaultExitCodeHandler : exitCodeHandler).accept(getExitCode(), null); //this may not be called if shutdown was initiated by a signal
}

Expand Down Expand Up @@ -435,6 +436,7 @@ public void run() {
currentApplication.stop();
}
currentApplication.awaitShutdown();
currentApplication = null;
System.out.flush();
System.err.flush();
}
Expand Down
2 changes: 1 addition & 1 deletion devtools/gradle/gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ kotlin = "2.0.0"
smallrye-config = "3.8.3"

junit5 = "5.10.3"
assertj = "3.26.0"
assertj = "3.26.3"

[plugins]
plugin-publish = { id = "com.gradle.plugin-publish", version.ref = "plugin-publish" }
Expand Down
1 change: 1 addition & 0 deletions docs/src/main/asciidoc/_attributes.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
:quickstarts-tree-url: ${quickstarts-base-url}/tree/main
// .
:hibernate-orm-docs-url: https://docs.jboss.org/hibernate/orm/{hibernate-orm-version-major-minor}/userguide/html_single/Hibernate_User_Guide.html
:hibernate-orm-dialect-docs-url: https://docs.jboss.org/hibernate/orm/{hibernate-orm-version-major-minor}/dialect/dialect.html
:hibernate-search-docs-url: https://docs.jboss.org/hibernate/search/{hibernate-search-version-major-minor}/reference/en-US/html_single/
// .
:amazon-services-guide: https://quarkiverse.github.io/quarkiverse-docs/quarkus-amazon-services/dev/index.html
Expand Down
Loading

0 comments on commit 2a21bec

Please sign in to comment.