Skip to content

Commit 502c7ea

Browse files
committed
solved #4890 Provide helpful error-message for BindException on quarkus.http.port
2 parents 848121c + 389d387 commit 502c7ea

File tree

346 files changed

+5186
-1657
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

346 files changed

+5186
-1657
lines changed

bom/application/pom.xml

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -106,13 +106,13 @@
106106
<jboss-modules.version>1.8.7.Final</jboss-modules.version>
107107
<jboss-threads.version>3.1.1.Final</jboss-threads.version>
108108
<vertx.version>3.9.3</vertx.version>
109-
<httpclient.version>4.5.12</httpclient.version>
109+
<httpclient.version>4.5.13</httpclient.version>
110110
<httpcore.version>4.4.13</httpcore.version>
111111
<httpasync.version>4.1.4</httpasync.version>
112112
<cronutils.version>9.1.1</cronutils.version>
113113
<quartz.version>2.3.2</quartz.version>
114114
<h2.version>1.4.197</h2.version> <!-- keep 1.4.197 as newer versions have severe regressions -->
115-
<postgresql-jdbc.version>42.2.16</postgresql-jdbc.version>
115+
<postgresql-jdbc.version>42.2.17</postgresql-jdbc.version>
116116
<mariadb-jdbc.version>2.7.0</mariadb-jdbc.version>
117117
<mysql-jdbc.version>8.0.21</mysql-jdbc.version>
118118
<mssql-jdbc.version>7.2.2.jre8</mssql-jdbc.version>
@@ -126,7 +126,7 @@
126126
<json-smart.version>2.3</json-smart.version>
127127
<infinispan.version>11.0.4.Final</infinispan.version>
128128
<infinispan.protostream.version>4.3.4.Final</infinispan.protostream.version>
129-
<caffeine.version>2.8.5</caffeine.version>
129+
<caffeine.version>2.8.6</caffeine.version>
130130
<netty.version>4.1.49.Final</netty.version>
131131
<reactive-streams.version>1.0.3</reactive-streams.version>
132132
<jboss-logging.version>3.4.1.Final</jboss-logging.version>
@@ -143,17 +143,17 @@
143143
<aws-lambda-java-events.version>3.4.0</aws-lambda-java-events.version>
144144
<aws-lambda-serverless-java-container.version>1.3.1</aws-lambda-serverless-java-container.version>
145145
<aws-xray.version>2.4.0</aws-xray.version>
146-
<awssdk.version>2.15.6</awssdk.version>
147-
<aws-alexa-sdk.version>2.35.0</aws-alexa-sdk.version>
146+
<awssdk.version>2.15.7</awssdk.version>
147+
<aws-alexa-sdk.version>2.35.1</aws-alexa-sdk.version>
148148
<azure-functions-java-library.version>1.3.0</azure-functions-java-library.version>
149149
<kotlin.version>1.3.72</kotlin.version>
150-
<dekorate.version>0.12.11</dekorate.version>
150+
<dekorate.version>0.13.2</dekorate.version>
151151
<maven-artifact-transfer.version>0.10.0</maven-artifact-transfer.version>
152152
<jline.version>2.14.6</jline.version>
153153
<maven-invoker.version>3.0.1</maven-invoker.version>
154154
<awaitility.version>4.0.3</awaitility.version>
155155
<jprocesses.version>1.6.5</jprocesses.version>
156-
<jboss-logmanager.version>1.0.4</jboss-logmanager.version>
156+
<jboss-logmanager.version>1.0.5</jboss-logmanager.version>
157157
<jgit.version>5.8.0.202006091008-r</jgit.version>
158158
<flyway.version>6.5.7</flyway.version>
159159
<yasson.version>1.0.8</yasson.version>
@@ -167,8 +167,6 @@
167167
<proton-j.version>0.33.6</proton-j.version>
168168
<okhttp.version>3.14.9</okhttp.version>
169169
<sentry.version>1.7.30</sentry.version>
170-
<!-- Used for integration tests, to make sure webjars work-->
171-
<bootstrap.version>3.1.0</bootstrap.version>
172170
<subethasmtp.version>3.1.7</subethasmtp.version>
173171
<hibernate-quarkus-local-cache.version>0.1.0</hibernate-quarkus-local-cache.version>
174172
<kubernetes-client.version>4.12.0</kubernetes-client.version>
@@ -763,6 +761,16 @@
763761
<artifactId>quarkus-hibernate-orm-rest-data-panache-deployment</artifactId>
764762
<version>${project.version}</version>
765763
</dependency>
764+
<dependency>
765+
<groupId>io.quarkus</groupId>
766+
<artifactId>quarkus-mongodb-rest-data-panache</artifactId>
767+
<version>${project.version}</version>
768+
</dependency>
769+
<dependency>
770+
<groupId>io.quarkus</groupId>
771+
<artifactId>quarkus-mongodb-rest-data-panache-deployment</artifactId>
772+
<version>${project.version}</version>
773+
</dependency>
766774
<dependency>
767775
<groupId>io.quarkus</groupId>
768776
<artifactId>quarkus-mongodb-panache</artifactId>
@@ -4293,12 +4301,6 @@
42934301
<version>${snakeyaml.version}</version>
42944302
</dependency>
42954303

4296-
<dependency>
4297-
<groupId>org.webjars</groupId>
4298-
<artifactId>bootstrap</artifactId>
4299-
<version>${bootstrap.version}</version>
4300-
</dependency>
4301-
43024304
<dependency>
43034305
<groupId>org.webjars</groupId>
43044306
<artifactId>webjars-locator-core</artifactId>

bom/test/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
<description>Dependency management for integration tests. Importable by third party extension developers.</description>
1717

1818
<properties>
19-
<debezium.version>1.2.5.Final</debezium.version>
19+
<debezium.version>1.3.0.Final</debezium.version>
2020
<testcontainers.version>1.14.3</testcontainers.version>
2121
</properties>
2222

build-parent/pom.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@
105105

106106
<boring-ssl.version>2.0.30.Final</boring-ssl.version>
107107

108+
<!-- Used for integration tests, to make sure webjars work-->
109+
<bootstrap.version>3.1.0</bootstrap.version>
110+
108111
<!-- revapi API check -->
109112
<revapi-maven-plugin.version>0.12.1</revapi-maven-plugin.version>
110113
<revapi-java-plugin.version>0.22.0</revapi-java-plugin.version>
@@ -236,6 +239,11 @@
236239
<scope>test</scope>
237240
<version>${boring-ssl.version}</version>
238241
</dependency>
242+
<dependency>
243+
<groupId>org.webjars</groupId>
244+
<artifactId>bootstrap</artifactId>
245+
<version>${bootstrap.version}</version>
246+
</dependency>
239247

240248
<dependency>
241249
<groupId>io.quarkus</groupId>

core/deployment/src/main/java/io/quarkus/deployment/Feature.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ public enum Feature {
6363
MONGODB_CLIENT,
6464
MONGODB_PANACHE,
6565
MONGODB_PANACHE_KOTLIN,
66+
MONGODB_REST_DATA_PANACHE,
6667
MUTINY,
6768
NARAYANA_JTA,
6869
NARAYANA_STM,
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package io.quarkus.deployment.builditem;
2+
3+
import java.util.Map;
4+
5+
import io.quarkus.builder.item.MultiBuildItem;
6+
7+
public final class AdditionalClassLoaderResourcesBuildItem extends MultiBuildItem {
8+
9+
final Map<String, byte[]> resources;
10+
11+
public AdditionalClassLoaderResourcesBuildItem(Map<String, byte[]> resources) {
12+
this.resources = resources;
13+
}
14+
15+
public Map<String, byte[]> getResources() {
16+
return resources;
17+
}
18+
19+
}

core/deployment/src/main/java/io/quarkus/deployment/builditem/GeneratedClassBuildItem.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ public GeneratedClassBuildItem(boolean applicationClass, String name, byte[] cla
1414
}
1515

1616
public GeneratedClassBuildItem(boolean applicationClass, String name, byte[] classData, String source) {
17+
if (name.startsWith("/")) {
18+
throw new IllegalArgumentException("Name cannot start with '/':" + name);
19+
}
1720
this.applicationClass = applicationClass;
1821
this.name = name;
1922
this.classData = classData;

core/deployment/src/main/java/io/quarkus/deployment/dev/IsolatedDevModeMain.java

Lines changed: 39 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import java.io.IOException;
99
import java.io.ObjectInputStream;
1010
import java.io.ObjectOutputStream;
11+
import java.net.BindException;
1112
import java.nio.file.Path;
1213
import java.nio.file.Paths;
1314
import java.util.ArrayList;
@@ -108,35 +109,40 @@ public void accept(Integer integer) {
108109
runner = start.runMainClass(context.getArgs());
109110
firstStartCompleted = true;
110111
} catch (Throwable t) {
111-
deploymentProblem = t;
112-
if (!augmentDone) {
113-
log.error("Failed to start quarkus", t);
112+
Throwable rootCause = t;
113+
while (rootCause.getCause() != null) {
114+
rootCause = rootCause.getCause();
114115
}
115-
if (!context.isAbortOnFailedStart()) {
116-
//we need to set this here, while we still have the correct TCCL
117-
//this is so the config is still valid, and we can read HTTP config from application.properties
118-
log.info("Attempting to start hot replacement endpoint to recover from previous Quarkus startup failure");
119-
if (RuntimeUpdatesProcessor.INSTANCE != null) {
120-
Thread.currentThread().setContextClassLoader(curatedApplication.getBaseRuntimeClassLoader());
121-
122-
try {
123-
if (!InitialConfigurator.DELAYED_HANDLER.isActivated()) {
124-
Class<?> cl = Thread.currentThread().getContextClassLoader()
125-
.loadClass(LoggingSetupRecorder.class.getName());
126-
cl.getMethod("handleFailedStart").invoke(null);
116+
if (!(rootCause instanceof BindException)) {
117+
deploymentProblem = t;
118+
if (!augmentDone) {
119+
log.error("Failed to start quarkus", t);
120+
}
121+
if (!context.isAbortOnFailedStart()) {
122+
//we need to set this here, while we still have the correct TCCL
123+
//this is so the config is still valid, and we can read HTTP config from application.properties
124+
log.info(
125+
"Attempting to start hot replacement endpoint to recover from previous Quarkus startup failure");
126+
if (RuntimeUpdatesProcessor.INSTANCE != null) {
127+
Thread.currentThread().setContextClassLoader(curatedApplication.getBaseRuntimeClassLoader());
128+
try {
129+
if (!InitialConfigurator.DELAYED_HANDLER.isActivated()) {
130+
Class<?> cl = Thread.currentThread().getContextClassLoader()
131+
.loadClass(LoggingSetupRecorder.class.getName());
132+
cl.getMethod("handleFailedStart").invoke(null);
133+
}
134+
RuntimeUpdatesProcessor.INSTANCE.startupFailed();
135+
} catch (Exception e) {
136+
close();
137+
log.error("Failed to recover after failed start", e);
138+
//this is the end of the road, we just exit
139+
//generally we only hit this if something is already listening on the HTTP port
140+
//or the system config is so broken we can't start HTTP
141+
System.exit(1);
127142
}
128-
RuntimeUpdatesProcessor.INSTANCE.startupFailed();
129-
} catch (Exception e) {
130-
close();
131-
log.error("Failed to recover after failed start", e);
132-
//this is the end of the road, we just exit
133-
//generally we only hit this if something is already listening on the HTTP port
134-
//or the system config is so broken we can't start HTTP
135-
System.exit(1);
136143
}
137144
}
138145
}
139-
140146
}
141147
} finally {
142148
Thread.currentThread().setContextClassLoader(old);
@@ -176,9 +182,15 @@ public synchronized void restartApp(Set<String> changedResources) {
176182
firstStartCompleted = true;
177183
} catch (Throwable t) {
178184
deploymentProblem = t;
179-
log.error("Failed to start quarkus", t);
180-
Thread.currentThread().setContextClassLoader(curatedApplication.getAugmentClassLoader());
181-
LoggingSetupRecorder.handleFailedStart();
185+
Throwable rootCause = t;
186+
while (rootCause.getCause() != null) {
187+
rootCause = rootCause.getCause();
188+
}
189+
if (!(rootCause instanceof BindException)) {
190+
log.error("Failed to start quarkus", t);
191+
Thread.currentThread().setContextClassLoader(curatedApplication.getAugmentClassLoader());
192+
LoggingSetupRecorder.handleFailedStart();
193+
}
182194
}
183195
} finally {
184196
restarting = false;
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package io.quarkus.deployment.steps;
2+
3+
import java.util.ArrayList;
4+
import java.util.Collections;
5+
import java.util.LinkedHashMap;
6+
import java.util.List;
7+
import java.util.Map;
8+
import java.util.Map.Entry;
9+
10+
import io.quarkus.bootstrap.classloading.QuarkusClassLoader;
11+
import io.quarkus.deployment.annotations.BuildProducer;
12+
import io.quarkus.deployment.annotations.BuildStep;
13+
import io.quarkus.deployment.builditem.AdditionalClassLoaderResourcesBuildItem;
14+
import io.quarkus.deployment.builditem.AdditionalIndexedClassesBuildItem;
15+
16+
public class AdditionalClassLoaderResourcesBuildStep {
17+
18+
@BuildStep
19+
void appendAdditionalClassloaderResources(BuildProducer<AdditionalIndexedClassesBuildItem> producer,
20+
List<AdditionalClassLoaderResourcesBuildItem> additionalResources) {
21+
22+
if (!additionalResources.isEmpty()) {
23+
QuarkusClassLoader cl = (QuarkusClassLoader) Thread.currentThread().getContextClassLoader();
24+
25+
Map<String, byte[]> collected = new LinkedHashMap<String, byte[]>();
26+
List<String> additionalClassesToIndex = new ArrayList<String>();
27+
for (AdditionalClassLoaderResourcesBuildItem item : additionalResources) {
28+
29+
for (Entry<String, byte[]> entry : item.getResources().entrySet()) {
30+
additionalClassesToIndex.add(entry.getKey());
31+
32+
collected.put(entry.getKey(), entry.getValue());
33+
// add it also as resources to allow index to work properly
34+
collected.put(entry.getKey().replace('.', '/') + ".class", entry.getValue());
35+
36+
}
37+
}
38+
39+
cl.reset(collected, Collections.emptyMap());
40+
// produce the AdditionalIndexedClassesBuildItem so this build step
41+
// is actually invoked and allow to directly index all the classes
42+
producer.produce(new AdditionalIndexedClassesBuildItem(additionalClassesToIndex.stream().toArray(String[]::new)));
43+
}
44+
}
45+
}

core/runtime/src/main/java/io/quarkus/runtime/ApplicationLifecycleManager.java

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.quarkus.runtime;
22

3+
import java.net.BindException;
34
import java.util.Locale;
45
import java.util.Objects;
56
import java.util.Set;
@@ -14,6 +15,7 @@
1415
import javax.enterprise.inject.spi.BeanManager;
1516
import javax.enterprise.inject.spi.CDI;
1617

18+
import org.eclipse.microprofile.config.spi.ConfigProviderResolver;
1719
import org.graalvm.nativeimage.ImageInfo;
1820
import org.jboss.logging.Logger;
1921
import org.wildfly.common.lock.Locks;
@@ -139,8 +141,28 @@ public static void run(Application application, Class<? extends QuarkusApplicati
139141
}
140142
} catch (Exception e) {
141143
if (exitCodeHandler == null) {
142-
Logger.getLogger(Application.class).errorv(e, "Failed to start application (with profile {0})",
143-
ProfileManager.getActiveProfile());
144+
Throwable rootCause = e;
145+
while (rootCause.getCause() != null) {
146+
rootCause = rootCause.getCause();
147+
}
148+
Logger applicationLogger = Logger.getLogger(Application.class);
149+
if (rootCause instanceof BindException) {
150+
int port = ConfigProviderResolver.instance().getConfig()
151+
.getOptionalValue("quarkus.http.port", Integer.class).orElse(8080);
152+
applicationLogger.error("Port " + port + " seems to be in use by another process. " +
153+
"Quarkus may already be running or the port is used by another application.");
154+
if (System.getProperty("os.name").startsWith("Windows")) {
155+
applicationLogger.info("Use 'netstat -a -b -n -o' to identify the process occupying the port.");
156+
applicationLogger.info("You can try to kill it with 'taskkill /PID <pid>' or via the Task Manager.");
157+
} else {
158+
applicationLogger
159+
.info("Use 'netstat -anop | grep " + port + "' to identify the process occupying the port.");
160+
applicationLogger.info("You can try to kill it with 'kill -9 <pid>'.");
161+
}
162+
} else {
163+
applicationLogger.errorv(rootCause, "Failed to start application (with profile {0})",
164+
ProfileManager.getActiveProfile());
165+
}
144166
}
145167
stateLock.lock();
146168
try {

core/test-extension/deployment/src/main/java/io/quarkus/extest/deployment/TestProcessor.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -275,14 +275,14 @@ void checkConfig() {
275275
+ buildTimeConfig.btStringOptWithDefault);
276276
}
277277
if (!buildTimeConfig.allValues.oov.equals(new ObjectOfValue("configPart1", "configPart2"))) {
278-
throw new IllegalStateException("buildTimeConfig.oov != configPart1+onfigPart2; " + buildTimeConfig.allValues.oov);
278+
throw new IllegalStateException("buildTimeConfig.oov != configPart1+configPart2; " + buildTimeConfig.allValues.oov);
279279
}
280280
if (!buildTimeConfig.allValues.oovWithDefault.equals(new ObjectOfValue("defaultPart1", "defaultPart2"))) {
281281
throw new IllegalStateException(
282282
"buildTimeConfig.oovWithDefault != defaultPart1+defaultPart2; " + buildTimeConfig.allValues.oovWithDefault);
283283
}
284284
if (!buildTimeConfig.allValues.ovo.equals(new ObjectValueOf("configPart1", "configPart2"))) {
285-
throw new IllegalStateException("buildTimeConfig.oov != configPart1+onfigPart2; " + buildTimeConfig.allValues.oov);
285+
throw new IllegalStateException("buildTimeConfig.oov != configPart1+configPart2; " + buildTimeConfig.allValues.oov);
286286
}
287287
if (!buildTimeConfig.allValues.ovoWithDefault.equals(new ObjectValueOf("defaultPart1", "defaultPart2"))) {
288288
throw new IllegalStateException(

0 commit comments

Comments
 (0)