You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@netbeans.apache.org by GitBox <gi...@apache.org> on 2022/02/15 17:45:12 UTC
[GitHub] [netbeans] sdedic opened a new pull request #3613: Support CompletableFuture in DialogDisplayer
sdedic opened a new pull request #3613:
URL: https://github.com/apache/netbeans/pull/3613
`DialogDisplayer` API allows to wait for dialog's close when using `notify` method but that wasted a thread to wait for the `notify` method to return. And all the goodies that `CompletableFuture` API can't be used, while this is a perfect example of a Future.
So this PR adds ```
public <T extends NotifyDescriptor> CompletableFuture<T> notifyCompletion(final T descriptor) {
```
that runs similar to `notifyLater`, but returns a Future that the continuation can chain after. There are important differences, hopefully described in the javadoc:
- the value is the `NotifyDescriptor` subclass itself. This is because for example `NotifyDescriptor.InputLine` has additional getters that are typically processed in the completion handler. This allows to pass NotifyDescriptors from one step to another wihtout a need for a variable in a upper scope or member variable that can be accessed from another closure.
- if the UI is cancelled / closed, this future **completes exceptionally** with a `CancellationException` (as if it was `Future.cancel()`ed). This allows the continuation chain to focus on the main job.
- chained processing runs in an **unspecified thread**, possibly the EDT; any long processing must be added using **async** methods of CompletableFuture so EDT is not blocked. Currently, when using and waiting for `notify`, the whole thread is dedicated.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: notifications-unsubscribe@netbeans.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@netbeans.apache.org
For additional commands, e-mail: notifications-help@netbeans.apache.org
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists
[GitHub] [netbeans] sdedic commented on a change in pull request #3613: Support CompletableFuture in DialogDisplayer
Posted by GitBox <gi...@apache.org>.
sdedic commented on a change in pull request #3613:
URL: https://github.com/apache/netbeans/pull/3613#discussion_r810136242
##########
File path: java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/ui/NotifyDescriptorAdapter.java
##########
@@ -277,45 +279,122 @@ public Object clientNotify() {
}
public CompletableFuture<Object> clientNotifyLater() {
+ return clientNotifyCompletion().thenApply(d -> d.getValue()).exceptionally(t -> {
+ if (t instanceof CompletionException) {
+ t = t.getCause();
+ }
+ if (!(t instanceof CancellationException)) {
+ LOG.log(Level.WARNING, "Exception occurred for {0}", descriptor);
+ LOG.log(Level.WARNING, "Exception stacktrace", t);
+ }
+ return null;
+ });
+ }
+
+ class Ctrl<T> extends CompletableFuture<T> {
+ private final CompletableFuture clientFuture;
+
+ public Ctrl(CompletableFuture clientFuture) {
+ this.clientFuture = clientFuture;
+ }
+
+ @Override
+ public boolean cancel(boolean mayInterruptIfRunning) {
+ // this is not exactly well synchronized, but with no synchronization in
+ // NotifyDescriptor the value cannot be set really atomically, but the dependents
+ // will be released during super.cancel() call.
+ boolean b = !isDone();
+ if (b) {
+ Object v = descriptor.getValue();
+ if (!(v == NotifyDescriptor.CANCEL_OPTION || v == NotifyDescriptor.CLOSED_OPTION)) {
+ descriptor.setValue(NotifyDescriptor.CANCEL_OPTION);
+ }
+ b &= clientFuture.cancel(mayInterruptIfRunning);
+ }
+ return super.cancel(mayInterruptIfRunning) || b;
+ }
+ }
+
+ public <T extends NotifyDescriptor> CompletableFuture<T> clientNotifyCompletion() {
+ // wrapper that allows to externally control the client's Future
if (descriptor instanceof NotifyDescriptor.InputLine) {
NotifyDescriptor.InputLine inp = (NotifyDescriptor.InputLine) descriptor;
ShowInputBoxParams params = new ShowInputBoxParams();
params.setPrompt(descriptor.getTitle());
params.setValue(inp.getInputText());
params.setPassword(descriptor instanceof NotifyDescriptor.PasswordLine);
CompletableFuture<String> newText = client.showInputBox(params);
- return newText.thenApply((item) -> {
+ Ctrl<T> ctrl = new Ctrl<>(newText);
+ newText.thenAccept((item) -> {
if (item == null) {
- return NotifyDescriptor.CLOSED_OPTION;
+ descriptor.setValue(NotifyDescriptor.CLOSED_OPTION);
+ ctrl.completeExceptionally(new CancellationException());
+ } else {
+ inp.setInputText(item);
+ descriptor.setValue(NotifyDescriptor.OK_OPTION);
+ ctrl.complete((T)descriptor);
}
- inp.setInputText(item);
- return NotifyDescriptor.OK_OPTION;
+ }).exceptionally(t -> {
+ if (t instanceof CompletionException) {
+ t = t.getCause();
+ }
+ ctrl.completeExceptionally(t);
+ return null;
});
+ return ctrl;
} else if (descriptor instanceof NotifyDescriptor.QuickPick) {
NotifyDescriptor.QuickPick qp = (NotifyDescriptor.QuickPick) descriptor;
Map<QuickPickItem, NotifyDescriptor.QuickPick.Item> items = new HashMap<>();
for (NotifyDescriptor.QuickPick.Item item : qp.getItems()) {
items.put(new QuickPickItem(item.getLabel(), item.getDescription(), null, item.isSelected(), null), item);
}
ShowQuickPickParams params = new ShowQuickPickParams(qp.getTitle(), qp.isMultipleSelection(), new ArrayList<>(items.keySet()));
- return client.showQuickPick(params).thenApply(selected -> {
+ CompletableFuture<List<QuickPickItem>> qpF = client.showQuickPick(params);
+ Ctrl<T> ctrl = new Ctrl<>(qpF);
+ qpF.thenAccept(selected -> {
if (selected == null) {
- return NotifyDescriptor.CLOSED_OPTION;
+ descriptor.setValue(NotifyDescriptor.CLOSED_OPTION);
+ ctrl.completeExceptionally(new CancellationException());
+ } else {
+ for (Map.Entry<QuickPickItem, NotifyDescriptor.QuickPick.Item> entry : items.entrySet()) {
+ entry.getValue().setSelected(selected.contains(entry.getKey()));
+ }
+ descriptor.setValue(NotifyDescriptor.OK_OPTION);
Review comment:
Recommitted in f32b076
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: notifications-unsubscribe@netbeans.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@netbeans.apache.org
For additional commands, e-mail: notifications-help@netbeans.apache.org
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists
[GitHub] [netbeans] JaroslavTulach commented on a change in pull request #3613: Support CompletableFuture in DialogDisplayer
Posted by GitBox <gi...@apache.org>.
JaroslavTulach commented on a change in pull request #3613:
URL: https://github.com/apache/netbeans/pull/3613#discussion_r807929480
##########
File path: platform/openide.dialogs/src/org/openide/DialogDisplayer.java
##########
@@ -98,6 +101,53 @@ public void run() {
}
});
}
+
+ /**
+ * Notify the user by a message box. The method may be called from any thread; the method
+ * returns immediately and the UI will be shown later, as in {@link #notifyLater}. Unlike
+ * {@link #notifyLater}, this method returns a {@link CompletableFuture} that will be
+ * completed when the UI closes. The value of the returned {@link CompletableFuture} is
+ * the descriptor itself: it's {@link NotifyDescriptor#getValue()} will be set to the
+ * closing option. If a subclass, like {@link NotifyDescriptor.InputLine} is used, the
+ * task can query other values of NotifyDescriptor, such as the text entered.
+ * Any exception thrown by {@link NotifyDescriptor} processing will be reported through {@link CompletableFuture#completeExceptionally}.
+ * <p>
+ * It is possible to call {@link CompletableFuture#cancel(boolean)} on the returned value.
+ * The implementation may (through it is not guaranteed) abort and hide the UI. If cancel() is
+ * called, the returned Future always completes exceptionally, with a {@link CancellationException}.
+ * <p>
+ * The thread that will execute the continuation or exception handler is undefined. Use usual
+ * precautions against EDT blocking and use {@link CompletableFuture#thenAcceptAsync(java.util.function.Consumer, java.util.concurrent.Executor)}
+ * or similar to execute in a specific thread. Prefer usage of {@link RequestProcessor} to the
+ * builtin thread pool.
+ * <div class="nonnormative">
+ * The following snippet is an example of chained dialogs (can be any other processing): {@codesnippet dialogdisplayer-notifyCompletion}
+ * </div>
+ * @param <T> actual subclass of {@link NotifyDescriptor} passed as a parameter.
+ * @param descriptor describes the UI / dialog.
+ * @return the descriptor instance.
+ * @since 7.60
+ */
+ public <T extends NotifyDescriptor> CompletableFuture<T> notifyCompletion(final T descriptor) {
Review comment:
I'd call the method `notifyFuture` - it returns a future, right?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: notifications-unsubscribe@netbeans.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@netbeans.apache.org
For additional commands, e-mail: notifications-help@netbeans.apache.org
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists
[GitHub] [netbeans] sdedic commented on a change in pull request #3613: Support CompletableFuture in DialogDisplayer
Posted by GitBox <gi...@apache.org>.
sdedic commented on a change in pull request #3613:
URL: https://github.com/apache/netbeans/pull/3613#discussion_r810136242
##########
File path: java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/ui/NotifyDescriptorAdapter.java
##########
@@ -277,45 +279,122 @@ public Object clientNotify() {
}
public CompletableFuture<Object> clientNotifyLater() {
+ return clientNotifyCompletion().thenApply(d -> d.getValue()).exceptionally(t -> {
+ if (t instanceof CompletionException) {
+ t = t.getCause();
+ }
+ if (!(t instanceof CancellationException)) {
+ LOG.log(Level.WARNING, "Exception occurred for {0}", descriptor);
+ LOG.log(Level.WARNING, "Exception stacktrace", t);
+ }
+ return null;
+ });
+ }
+
+ class Ctrl<T> extends CompletableFuture<T> {
+ private final CompletableFuture clientFuture;
+
+ public Ctrl(CompletableFuture clientFuture) {
+ this.clientFuture = clientFuture;
+ }
+
+ @Override
+ public boolean cancel(boolean mayInterruptIfRunning) {
+ // this is not exactly well synchronized, but with no synchronization in
+ // NotifyDescriptor the value cannot be set really atomically, but the dependents
+ // will be released during super.cancel() call.
+ boolean b = !isDone();
+ if (b) {
+ Object v = descriptor.getValue();
+ if (!(v == NotifyDescriptor.CANCEL_OPTION || v == NotifyDescriptor.CLOSED_OPTION)) {
+ descriptor.setValue(NotifyDescriptor.CANCEL_OPTION);
+ }
+ b &= clientFuture.cancel(mayInterruptIfRunning);
+ }
+ return super.cancel(mayInterruptIfRunning) || b;
+ }
+ }
+
+ public <T extends NotifyDescriptor> CompletableFuture<T> clientNotifyCompletion() {
+ // wrapper that allows to externally control the client's Future
if (descriptor instanceof NotifyDescriptor.InputLine) {
NotifyDescriptor.InputLine inp = (NotifyDescriptor.InputLine) descriptor;
ShowInputBoxParams params = new ShowInputBoxParams();
params.setPrompt(descriptor.getTitle());
params.setValue(inp.getInputText());
params.setPassword(descriptor instanceof NotifyDescriptor.PasswordLine);
CompletableFuture<String> newText = client.showInputBox(params);
- return newText.thenApply((item) -> {
+ Ctrl<T> ctrl = new Ctrl<>(newText);
+ newText.thenAccept((item) -> {
if (item == null) {
- return NotifyDescriptor.CLOSED_OPTION;
+ descriptor.setValue(NotifyDescriptor.CLOSED_OPTION);
+ ctrl.completeExceptionally(new CancellationException());
+ } else {
+ inp.setInputText(item);
+ descriptor.setValue(NotifyDescriptor.OK_OPTION);
+ ctrl.complete((T)descriptor);
}
- inp.setInputText(item);
- return NotifyDescriptor.OK_OPTION;
+ }).exceptionally(t -> {
+ if (t instanceof CompletionException) {
+ t = t.getCause();
+ }
+ ctrl.completeExceptionally(t);
+ return null;
});
+ return ctrl;
} else if (descriptor instanceof NotifyDescriptor.QuickPick) {
NotifyDescriptor.QuickPick qp = (NotifyDescriptor.QuickPick) descriptor;
Map<QuickPickItem, NotifyDescriptor.QuickPick.Item> items = new HashMap<>();
for (NotifyDescriptor.QuickPick.Item item : qp.getItems()) {
items.put(new QuickPickItem(item.getLabel(), item.getDescription(), null, item.isSelected(), null), item);
}
ShowQuickPickParams params = new ShowQuickPickParams(qp.getTitle(), qp.isMultipleSelection(), new ArrayList<>(items.keySet()));
- return client.showQuickPick(params).thenApply(selected -> {
+ CompletableFuture<List<QuickPickItem>> qpF = client.showQuickPick(params);
+ Ctrl<T> ctrl = new Ctrl<>(qpF);
+ qpF.thenAccept(selected -> {
if (selected == null) {
- return NotifyDescriptor.CLOSED_OPTION;
+ descriptor.setValue(NotifyDescriptor.CLOSED_OPTION);
+ ctrl.completeExceptionally(new CancellationException());
+ } else {
+ for (Map.Entry<QuickPickItem, NotifyDescriptor.QuickPick.Item> entry : items.entrySet()) {
+ entry.getValue().setSelected(selected.contains(entry.getKey()));
+ }
+ descriptor.setValue(NotifyDescriptor.OK_OPTION);
Review comment:
Recommitted as 5da86ff
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: notifications-unsubscribe@netbeans.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@netbeans.apache.org
For additional commands, e-mail: notifications-help@netbeans.apache.org
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists
[GitHub] [netbeans] sdedic commented on pull request #3613: Support CompletableFuture in DialogDisplayer
Posted by GitBox <gi...@apache.org>.
sdedic commented on pull request #3613:
URL: https://github.com/apache/netbeans/pull/3613#issuecomment-1045965307
All OK again except the GraalVM LTS test, see comments above. Finally merging.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: notifications-unsubscribe@netbeans.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@netbeans.apache.org
For additional commands, e-mail: notifications-help@netbeans.apache.org
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists
[GitHub] [netbeans] sdedic merged pull request #3613: Support CompletableFuture in DialogDisplayer
Posted by GitBox <gi...@apache.org>.
sdedic merged pull request #3613:
URL: https://github.com/apache/netbeans/pull/3613
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: notifications-unsubscribe@netbeans.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@netbeans.apache.org
For additional commands, e-mail: notifications-help@netbeans.apache.org
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists
[GitHub] [netbeans] dbalek commented on a change in pull request #3613: Support CompletableFuture in DialogDisplayer
Posted by GitBox <gi...@apache.org>.
dbalek commented on a change in pull request #3613:
URL: https://github.com/apache/netbeans/pull/3613#discussion_r810124980
##########
File path: java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/ui/NotifyDescriptorAdapter.java
##########
@@ -277,45 +279,122 @@ public Object clientNotify() {
}
public CompletableFuture<Object> clientNotifyLater() {
+ return clientNotifyCompletion().thenApply(d -> d.getValue()).exceptionally(t -> {
+ if (t instanceof CompletionException) {
+ t = t.getCause();
+ }
+ if (!(t instanceof CancellationException)) {
+ LOG.log(Level.WARNING, "Exception occurred for {0}", descriptor);
+ LOG.log(Level.WARNING, "Exception stacktrace", t);
+ }
+ return null;
+ });
+ }
+
+ class Ctrl<T> extends CompletableFuture<T> {
+ private final CompletableFuture clientFuture;
+
+ public Ctrl(CompletableFuture clientFuture) {
+ this.clientFuture = clientFuture;
+ }
+
+ @Override
+ public boolean cancel(boolean mayInterruptIfRunning) {
+ // this is not exactly well synchronized, but with no synchronization in
+ // NotifyDescriptor the value cannot be set really atomically, but the dependents
+ // will be released during super.cancel() call.
+ boolean b = !isDone();
+ if (b) {
+ Object v = descriptor.getValue();
+ if (!(v == NotifyDescriptor.CANCEL_OPTION || v == NotifyDescriptor.CLOSED_OPTION)) {
+ descriptor.setValue(NotifyDescriptor.CANCEL_OPTION);
+ }
+ b &= clientFuture.cancel(mayInterruptIfRunning);
+ }
+ return super.cancel(mayInterruptIfRunning) || b;
+ }
+ }
+
+ public <T extends NotifyDescriptor> CompletableFuture<T> clientNotifyCompletion() {
+ // wrapper that allows to externally control the client's Future
if (descriptor instanceof NotifyDescriptor.InputLine) {
NotifyDescriptor.InputLine inp = (NotifyDescriptor.InputLine) descriptor;
ShowInputBoxParams params = new ShowInputBoxParams();
params.setPrompt(descriptor.getTitle());
params.setValue(inp.getInputText());
params.setPassword(descriptor instanceof NotifyDescriptor.PasswordLine);
CompletableFuture<String> newText = client.showInputBox(params);
- return newText.thenApply((item) -> {
+ Ctrl<T> ctrl = new Ctrl<>(newText);
+ newText.thenAccept((item) -> {
if (item == null) {
- return NotifyDescriptor.CLOSED_OPTION;
+ descriptor.setValue(NotifyDescriptor.CLOSED_OPTION);
+ ctrl.completeExceptionally(new CancellationException());
+ } else {
+ inp.setInputText(item);
+ descriptor.setValue(NotifyDescriptor.OK_OPTION);
+ ctrl.complete((T)descriptor);
}
- inp.setInputText(item);
- return NotifyDescriptor.OK_OPTION;
+ }).exceptionally(t -> {
+ if (t instanceof CompletionException) {
+ t = t.getCause();
+ }
+ ctrl.completeExceptionally(t);
+ return null;
});
+ return ctrl;
} else if (descriptor instanceof NotifyDescriptor.QuickPick) {
NotifyDescriptor.QuickPick qp = (NotifyDescriptor.QuickPick) descriptor;
Map<QuickPickItem, NotifyDescriptor.QuickPick.Item> items = new HashMap<>();
for (NotifyDescriptor.QuickPick.Item item : qp.getItems()) {
items.put(new QuickPickItem(item.getLabel(), item.getDescription(), null, item.isSelected(), null), item);
}
ShowQuickPickParams params = new ShowQuickPickParams(qp.getTitle(), qp.isMultipleSelection(), new ArrayList<>(items.keySet()));
- return client.showQuickPick(params).thenApply(selected -> {
+ CompletableFuture<List<QuickPickItem>> qpF = client.showQuickPick(params);
+ Ctrl<T> ctrl = new Ctrl<>(qpF);
+ qpF.thenAccept(selected -> {
if (selected == null) {
- return NotifyDescriptor.CLOSED_OPTION;
+ descriptor.setValue(NotifyDescriptor.CLOSED_OPTION);
+ ctrl.completeExceptionally(new CancellationException());
+ } else {
+ for (Map.Entry<QuickPickItem, NotifyDescriptor.QuickPick.Item> entry : items.entrySet()) {
+ entry.getValue().setSelected(selected.contains(entry.getKey()));
+ }
+ descriptor.setValue(NotifyDescriptor.OK_OPTION);
Review comment:
Missing `ctrl.complete((T)descriptor)` ?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: notifications-unsubscribe@netbeans.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@netbeans.apache.org
For additional commands, e-mail: notifications-help@netbeans.apache.org
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists
[GitHub] [netbeans] sdedic commented on pull request #3613: Support CompletableFuture in DialogDisplayer
Posted by GitBox <gi...@apache.org>.
sdedic commented on pull request #3613:
URL: https://github.com/apache/netbeans/pull/3613#issuecomment-1044648578
Rebased on latest master; adapted to changes added to LSP DialogDisplayerImpl by #3584
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: notifications-unsubscribe@netbeans.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@netbeans.apache.org
For additional commands, e-mail: notifications-help@netbeans.apache.org
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists
[GitHub] [netbeans] sdedic commented on pull request #3613: Support CompletableFuture in DialogDisplayer
Posted by GitBox <gi...@apache.org>.
sdedic commented on pull request #3613:
URL: https://github.com/apache/netbeans/pull/3613#issuecomment-1044261280
According to @entlicher the reason for the failed test `DebugAllBaseTest` is most probably already in the master, not in this PR. See for example https://app.travis-ci.com/github/apache/netbeans/builds/246681735 which is failing with the same message.
https://issues.apache.org/jira/browse/NETBEANS-6458 was filled for the suspected cause, but not fixed yet.
Merging.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: notifications-unsubscribe@netbeans.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@netbeans.apache.org
For additional commands, e-mail: notifications-help@netbeans.apache.org
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists