Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: the exception of plugin context has been closed when plugin restart #2518

Merged
merged 1 commit into from
Oct 9, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions src/main/java/run/halo/app/config/ExtensionConfiguration.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package run.halo.app.config;

import io.micrometer.core.instrument.MeterRegistry;
import org.pf4j.PluginManager;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
@@ -54,6 +53,7 @@
import run.halo.app.infra.ExternalUrlSupplier;
import run.halo.app.infra.SystemConfigurableEnvironmentFetcher;
import run.halo.app.infra.properties.HaloProperties;
import run.halo.app.plugin.ExtensionComponentsFinder;
import run.halo.app.plugin.HaloPluginManager;
import run.halo.app.plugin.resources.JsBundleRuleProvider;
import run.halo.app.theme.router.TemplateRouteManager;
@@ -183,10 +183,12 @@ Controller systemSettingController(ExtensionClient client,
}

@Bean
Controller attachmentController(ExtensionClient client, PluginManager pluginManager,
Controller attachmentController(ExtensionClient client,
ExtensionComponentsFinder extensionComponentsFinder,
ExternalUrlSupplier externalUrl) {
return new ControllerBuilder("attachment-controller", client)
.reconciler(new AttachmentReconciler(client, pluginManager, externalUrl))
.reconciler(
new AttachmentReconciler(client, extensionComponentsFinder, externalUrl))
.extension(new Attachment())
.build();
}
Original file line number Diff line number Diff line change
@@ -13,7 +13,6 @@
import java.util.Optional;
import java.util.function.Predicate;
import lombok.extern.slf4j.Slf4j;
import org.pf4j.PluginManager;
import org.springdoc.core.fn.builders.requestbody.Builder;
import org.springdoc.webflux.core.fn.SpringdocRouteBuilder;
import org.springframework.http.HttpStatus;
@@ -43,18 +42,20 @@
import run.halo.app.extension.Ref;
import run.halo.app.extension.router.IListRequest;
import run.halo.app.extension.router.IListRequest.QueryListRequest;
import run.halo.app.plugin.ExtensionComponentsFinder;

@Slf4j
@Component
public class AttachmentEndpoint implements CustomEndpoint {

private final ReactiveExtensionClient client;

private final PluginManager pluginManager;
private final ExtensionComponentsFinder extensionComponentsFinder;

public AttachmentEndpoint(ReactiveExtensionClient client, PluginManager pluginManager) {
public AttachmentEndpoint(ReactiveExtensionClient client,
ExtensionComponentsFinder extensionComponentsFinder) {
this.client = client;
this.pluginManager = pluginManager;
this.extensionComponentsFinder = extensionComponentsFinder;
}

@Override
@@ -108,7 +109,7 @@ Mono<ServerResponse> upload(ServerRequest request) {
})
// find the proper handler to handle the attachment
.flatMap(uploadOption -> Flux.fromIterable(
pluginManager.getExtensions(AttachmentHandler.class))
extensionComponentsFinder.getExtensions(AttachmentHandler.class))
.concatMap(uploadHandler -> uploadHandler.upload(uploadOption)
.doOnNext(attachment -> {
var spec = attachment.getSpec();
Original file line number Diff line number Diff line change
@@ -6,7 +6,6 @@
import java.util.Objects;
import java.util.Set;
import lombok.extern.slf4j.Slf4j;
import org.pf4j.PluginManager;
import org.springframework.web.util.UriUtils;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@@ -22,20 +21,22 @@
import run.halo.app.extension.controller.Reconciler.Request;
import run.halo.app.infra.ExternalUrlSupplier;
import run.halo.app.infra.exception.NotFoundException;
import run.halo.app.plugin.ExtensionComponentsFinder;

@Slf4j
public class AttachmentReconciler implements Reconciler<Request> {

private final ExtensionClient client;

private final PluginManager pluginManager;
private final ExtensionComponentsFinder extensionComponentsFinder;

private final ExternalUrlSupplier externalUrl;

public AttachmentReconciler(ExtensionClient client, PluginManager pluginManager,
public AttachmentReconciler(ExtensionClient client,
ExtensionComponentsFinder extensionComponentsFinder,
ExternalUrlSupplier externalUrl) {
this.client = client;
this.pluginManager = pluginManager;
this.extensionComponentsFinder = extensionComponentsFinder;
this.externalUrl = externalUrl;
}

@@ -51,7 +52,7 @@ public Result reconcile(Request request) {
client.fetch(ConfigMap.class, policy.getSpec().getConfigMapRef().getName())
.orElseThrow();
var deleteOption = new DeleteOption(attachment, policy, configMap);
Flux.fromIterable(pluginManager.getExtensions(AttachmentHandler.class))
Flux.fromIterable(extensionComponentsFinder.getExtensions(AttachmentHandler.class))
.concatMap(handler -> handler.delete(deleteOption)).next().switchIfEmpty(
Mono.error(() -> new NotFoundException(
"No suitable handler found to delete the attachment")))
17 changes: 0 additions & 17 deletions src/main/java/run/halo/app/plugin/BasePlugin.java
Original file line number Diff line number Diff line change
@@ -14,27 +14,10 @@
@Slf4j
public class BasePlugin extends Plugin {

private PluginApplicationContext applicationContext;

public BasePlugin(PluginWrapper wrapper) {
super(wrapper);
}

/**
* <p>Lazy initialization plugin application context,
* avoid being unable to get context when system start scan plugin.</p>
* <p>The plugin application context is not created until the plug-in is started.</p>
*
* @return Plugin application context.
*/
public final synchronized PluginApplicationContext getApplicationContext() {
if (applicationContext == null) {
applicationContext =
getPluginManager().getPluginApplicationContext(this.wrapper.getPluginId());
}
return applicationContext;
}

private HaloPluginManager getPluginManager() {
return (HaloPluginManager) getWrapper().getPluginManager();
}
21 changes: 0 additions & 21 deletions src/main/java/run/halo/app/plugin/HaloPluginManager.java
Original file line number Diff line number Diff line change
@@ -7,8 +7,6 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import lombok.extern.slf4j.Slf4j;
import org.pf4j.DefaultPluginManager;
import org.pf4j.ExtensionFactory;
@@ -26,7 +24,6 @@
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.lang.NonNull;
import run.halo.app.plugin.event.HaloPluginBeforeStopEvent;
import run.halo.app.plugin.event.HaloPluginLoadedEvent;
@@ -111,24 +108,6 @@ protected PluginDescriptorFinder createPluginDescriptorFinder() {
return new YamlPluginDescriptorFinder();
}

@Override
public <T> List<T> getExtensions(Class<T> type) {
// we will collect implementations from Halo core at last.
return Stream.concat(
this.getExtensions(extensionFinder.find(type))
.stream(),
rootApplicationContext.getBeansOfType(type)
.values()
.stream()
.sorted(AnnotationAwareOrderComparator.INSTANCE))
.collect(Collectors.toList());
}

@Override
public <T> List<T> getExtensions(Class<T> type, String pluginId) {
return this.getExtensions(extensionFinder.find(type, pluginId));
}

@Override
protected void firePluginStateEvent(PluginStateEvent event) {
rootApplicationContext.publishEvent(
Original file line number Diff line number Diff line change
@@ -165,7 +165,9 @@ protected <T> Optional<PluginApplicationContext> getPluginApplicationContextBy(
" Extension class ' " + nameOf(extensionClass) + "' belongs to halo-plugin '"
+ nameOf(plugin)
+ "' and will be autowired by using its application context.");
applicationContext = ((BasePlugin) plugin).getApplicationContext();
applicationContext = ExtensionContextRegistry.getInstance()
.getByPluginId(plugin.getWrapper().getPluginId());
return Optional.of(applicationContext);
} else if (this.pluginManager instanceof HaloPluginManager && plugin != null) {
log.debug(" Extension class ' " + nameOf(extensionClass)
+ "' belongs to a non halo-plugin (or main application)"
Original file line number Diff line number Diff line change
@@ -16,7 +16,6 @@
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.pf4j.PluginManager;
import org.springframework.http.MediaType;
import org.springframework.http.client.MultipartBodyBuilder;
import org.springframework.test.web.reactive.server.WebTestClient;
@@ -29,6 +28,7 @@
import run.halo.app.extension.Metadata;
import run.halo.app.extension.ReactiveExtensionClient;
import run.halo.app.extension.Ref;
import run.halo.app.plugin.ExtensionComponentsFinder;

@ExtendWith(MockitoExtension.class)
class AttachmentEndpointTest {
@@ -37,7 +37,7 @@ class AttachmentEndpointTest {
ReactiveExtensionClient client;

@Mock
PluginManager pluginManager;
ExtensionComponentsFinder extensionComponentsFinder;

@InjectMocks
AttachmentEndpoint endpoint;
@@ -116,7 +116,8 @@ void shouldUploadSuccessfully() {
attachment.setMetadata(metadata);

when(handler.upload(any())).thenReturn(Mono.just(attachment));
when(pluginManager.getExtensions(AttachmentHandler.class)).thenReturn(List.of(handler));
when(extensionComponentsFinder.getExtensions(AttachmentHandler.class)).thenReturn(
List.of(handler));
when(client.create(attachment)).thenReturn(Mono.just(attachment));

var builder = new MultipartBodyBuilder();
@@ -143,7 +144,7 @@ void shouldUploadSuccessfully() {
verify(client).get(Policy.class, "fake-policy");
verify(client).get(ConfigMap.class, "fake-configmap");
verify(client).create(attachment);
verify(pluginManager).getExtensions(AttachmentHandler.class);
verify(extensionComponentsFinder).getExtensions(AttachmentHandler.class);
verify(handler).upload(any());
}
}