Skip to content

Commit

Permalink
Prefer connecting via JMX to process. New UI for show/refresh/hide
Browse files Browse the repository at this point in the history
  • Loading branch information
BoykoAlex committed Apr 4, 2024
1 parent 88ae931 commit eb3d46d
Show file tree
Hide file tree
Showing 28 changed files with 621 additions and 188 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="output" path="target/classes"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nul
org.eclipse.jdt.core.compiler.annotation.nullable.secondary=
org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
org.eclipse.jdt.core.compiler.compliance=11
org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
org.eclipse.jdt.core.compiler.compliance=17
org.eclipse.jdt.core.compiler.problem.APILeak=warning
org.eclipse.jdt.core.compiler.problem.annotatedTypeArgumentToUnannotated=info
org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
Expand Down Expand Up @@ -109,4 +109,4 @@ org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
org.eclipse.jdt.core.compiler.release=enabled
org.eclipse.jdt.core.compiler.source=11
org.eclipse.jdt.core.compiler.source=17
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2015, 2022 Pivotal, Inc.
* Copyright (c) 2015, 2024 Pivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
Expand All @@ -10,7 +10,6 @@
*******************************************************************************/
package org.springframework.ide.eclipse.boot.dash;

import java.time.Duration;
import java.util.Arrays;
import java.util.Map;

Expand All @@ -23,6 +22,7 @@
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.ImageRegistry;
import org.eclipse.ui.plugin.AbstractUIPlugin;
Expand All @@ -36,15 +36,12 @@
import org.springframework.ide.eclipse.boot.dash.model.BootDashViewModel;
import org.springframework.ide.eclipse.boot.dash.model.DefaultBootDashModelContext;
import org.springframework.ide.eclipse.boot.dash.model.LocalBootDashModel;
import org.springframework.ide.eclipse.boot.dash.model.RunState;
import org.springframework.ide.eclipse.boot.dash.model.RunTargets;
import org.springframework.ide.eclipse.boot.dash.util.LaunchConfRunStateTracker;
import org.springframework.ide.eclipse.boot.dash.util.RunStateTracker.RunStateListener;
import org.springframework.ide.eclipse.boot.launch.BootLaunchConfigurationDelegate;
import org.springsource.ide.eclipse.commons.livexp.util.Log;

import reactor.core.publisher.Mono;

/**
* The activator class controls the plug-in life cycle
*/
Expand Down Expand Up @@ -195,35 +192,46 @@ public static IEclipsePreferences getPreferences() {

@Override
public void stateChanged(ILaunchConfiguration owner) {
if (BootLaunchConfigurationDelegate.getEnableJmx(owner) && BootLaunchConfigurationDelegate.getAutoConnect(owner)) {
if (BootLaunchConfigurationDelegate.getEnableJmx(owner)) {
IJavaProject project = JavaCore.create(BootLaunchConfigurationDelegate.getProject(owner));
try {
if (project != null && Arrays.stream(project.getResolvedClasspath(true)).anyMatch(BootPropertyTester::isActuatorJar)) {
LocalBootDashModel localModel = (LocalBootDashModel) getModel().getSectionByTargetId(RunTargets.LOCAL.getId());
LaunchConfRunStateTracker tracker = localModel.getLaunchConfRunStateTracker();
RunState state = tracker.getState(owner);
if (state == RunState.RUNNING || state == RunState.DEBUGGING) {
switch (tracker.getState(owner)) {
case RUNNING:
case DEBUGGING:
for (ILaunch l : DebugPlugin.getDefault().getLaunchManager().getLaunches()) {
if (l.getLaunchConfiguration() == owner) {
for (IProcess p : l.getProcesses()) {
String pid = p.getAttribute(IProcess.ATTR_PROCESS_ID);
if (pid != null) {
CommandInfo cmd = new CommandInfo("sts/livedata/connect",
Map.of("processKey", pid));

// The delay seems to be necessary for the moment. Although the process is created VM attach API may not work at early stages of the process run.
// "VirtualMachine.list()" call may not list the newly created process which means the process is gone and triggers disconnect.
// If lifecycle management is enabled the ready state seem to be a great indicator of a boot process fully started.
// TODO: explore health endpoint perhaps instead of ready state under Admin endpoint.
// Flux.fromIterable(servers).flatMap(s -> Mono.delay(Duration.ofMillis(500)).then(s.executeCommand(cmd))).subscribe();
Mono.delay(Duration.ofMillis(500)).then(LiveProcessCommandsExecutor.getDefault().executeCommand(cmd)).subscribe();

CommandInfo cmd = new CommandInfo("sts/livedata/localAdd", Map.of(
"host", "127.0.0.1",
"port", l.getAttribute(BootLaunchConfigurationDelegate.JMX_PORT),
"urlScheme", "http",
"jmxurl", "service:jmx:rmi:///jndi/rmi://127.0.0.1:%s/jmxrmi".formatted(l.getAttribute(BootLaunchConfigurationDelegate.JMX_PORT)),
"manualConnect", !BootLaunchConfigurationDelegate.getAutoConnect(owner),
"processId", pid,
"processName", owner.getAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, p.getLabel()),
"projectName", project.getProject().getName()
));

LiveProcessCommandsExecutor.getDefault().executeCommand(cmd).subscribe();
}
}
}
}
break;
case INACTIVE:
for (ILaunch l : DebugPlugin.getDefault().getLaunchManager().getLaunches()) {
if (l.getLaunchConfiguration() == owner && l.getAttribute(BootLaunchConfigurationDelegate.JMX_PORT) != null) {
String jmxUrl = "service:jmx:rmi:///jndi/rmi://127.0.0.1:%s/jmxrmi".formatted(l.getAttribute(BootLaunchConfigurationDelegate.JMX_PORT));
LiveProcessCommandsExecutor.getDefault().executeCommand("sts/livedata/localRemove", jmxUrl).subscribe();
}
}
default:
}

}
} catch (Exception e) {
getLog().error("Failed to connect to Boot app", e);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2019 Pivotal Software, Inc.
* Copyright (c) 2019, 2024 Pivotal Software, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
Expand All @@ -16,9 +16,9 @@
public class CommandInfo {

public final String command;
public final Map<String,String> info;
public final Map<String,?> info;

public CommandInfo(String command, Map<String, String> info) {
public CommandInfo(String command, Map<String, ?> info) {
super();
this.command = command;
this.info = info;
Expand All @@ -27,7 +27,7 @@ public CommandInfo(String command, Map<String, String> info) {
@Override
public String toString() {
StringBuilder s = new StringBuilder("CommandInfo("+command+", {\n");
for (Entry<String, String> e : info.entrySet()) {
for (Entry<String, ?> e : info.entrySet()) {
s.append(" "+e.getKey() +": "+e.getValue()+"\n");
}
s.append("})");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,12 @@ public Mono<Void> executeCommand(CommandInfo cmd) {
))).thenAccept(l -> {}));
}

@Override
public Mono<Void> executeCommand(String command, Object... params) {
return Mono.fromFuture(BootLsCommandUtils.getLanguageServers(command).collectAll(ls -> ls.getWorkspaceService().executeCommand(new ExecuteCommandParams(
command,
ImmutableList.of(params)
))).thenAccept(l -> {}));
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2019, 2023 Pivotal Software, Inc.
* Copyright (c) 2019, 2024 Pivotal Software, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
Expand Down Expand Up @@ -77,15 +77,24 @@ public class ExecuteCommandAction extends AbstractBootDashElementsAction {
public ExecuteCommandAction(CommandInfo commandInfo) {
super(params);
this.commandInfo = commandInfo;
String command = commandInfo.command;
int lastSlash = command.lastIndexOf("/");
String humanReadableCommand = command.substring(lastSlash+1);
humanReadableCommand = humanReadableCommand.substring(0, 1).toUpperCase() + humanReadableCommand.substring(1);
this.projectName = commandInfo.info.get("projectName");
label = humanReadableCommand + " "+commandInfo.info.get("label");
this.projectName = (String) commandInfo.info.get("projectName");
label = computeLabel(commandInfo);
this.setText(label);
}

private String computeLabel(CommandInfo commandInfo) {
switch (commandInfo.command) {
case "sts/livedata/connect":
return "Show Live Data from: %s".formatted(commandInfo.info.get("label"));
case "sts/livedata/refresh":
return "Refresh Live Data from: %s".formatted(commandInfo.info.get("label"));
case "sts/livedata/disconnect":
return "Hide Live Data from: %s".formatted(commandInfo.info.get("label"));
default:
}
return (String) commandInfo.info.get("label");
}

public String getProjectName() {
return projectName;
}
Expand Down Expand Up @@ -115,7 +124,7 @@ public void run() {
}

public String getProcessId() {
return commandInfo.info.get("processId");
return (String) commandInfo.info.get("processId");
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2019, 2023 Pivotal Software, Inc.
* Copyright (c) 2019, 2024 Pivotal Software, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
Expand All @@ -17,6 +17,7 @@ public interface LiveProcessCommandsExecutor {

Flux<CommandInfo> listCommands();
Mono<Void> executeCommand(CommandInfo cmd);
Mono<Void> executeCommand(String command, Object... params);

static LiveProcessCommandsExecutor getDefault() {
return new DefaultLiveProcessCommandExecutor();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public class Constants {

public static final String PLUGIN_ID = "org.springframework.tooling.boot.ls";

public static final String PREF_LIVE_INFORMATION_ALL_JVM_PROCESSES = "boot-java.live-information.all-local-java-processes";
public static final String PREF_LIVE_INFORMATION_FETCH_DATA_RETRY_MAX_NO = "boot-java.live-information.fetch-data.max-retries";
public static final String PREF_LIVE_INFORMATION_FETCH_DATA_RETRY_DELAY_IN_SECONDS = "boot-java.live-information.fetch-data.retry-delay-in-seconds";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ private void sendConfiguration() {
liveInformationFetchData.put("retry-delay-in-seconds", preferenceStore.getInt(Constants.PREF_LIVE_INFORMATION_FETCH_DATA_RETRY_DELAY_IN_SECONDS));

liveInformation.put("fetch-data", liveInformationFetchData);
liveInformation.put("all-local-java-processes", preferenceStore.getBoolean(Constants.PREF_LIVE_INFORMATION_ALL_JVM_PROCESSES));

supportXML.put("on", preferenceStore.getBoolean(Constants.PREF_SUPPORT_SPRING_XML_CONFIGS));
supportXML.put("scan-folders", preferenceStore.getString(Constants.PREF_XML_CONFIGS_SCAN_FOLDERS));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,13 @@ public LiveProcessCommandElement(String processKey, String label, String action)
@Override
public String getLabel() {
if (COMMAND_REFRESH.equals(action)) {
return "Refresh Live Data for: " + label;
return "Refresh Live Data from: " + label;
}
else if (COMMAND_CONNECT.equals(action)) {
return "Show live data for: " + label;
return "Show Live Data from: " + label;
}
else if (COMMAND_DISCONNECT.equals(action)) {
return "Disconnect live data from: " + label;
return "Hide Live Data from: " + label;
}
else {
// error case
Expand Down
Loading

0 comments on commit eb3d46d

Please sign in to comment.