Skip to content

Commit

Permalink
[WFARQ-165] Upgrade wildfly-plugin-tools to 1.1.0.Final. Allow for in…
Browse files Browse the repository at this point in the history
…jection of the ServerManager from the plugin tools.

Add some server setup utilities and a DeploymentDescriptors utility.

https://issues.redhat.com/browse/WFARQ-165
Signed-off-by: James R. Perkins <[email protected]>
  • Loading branch information
jamezp committed Apr 19, 2024
1 parent 28677f4 commit 5d6d5df
Show file tree
Hide file tree
Showing 25 changed files with 2,064 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import java.util.Collections;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Future;

Expand All @@ -39,7 +40,6 @@
import org.jboss.logging.Logger;
import org.jboss.shrinkwrap.api.Archive;
import org.jboss.shrinkwrap.api.exporter.ZipExporter;
import org.wildfly.common.Assert;
import org.wildfly.plugin.tools.Deployment;
import org.wildfly.plugin.tools.DeploymentManager;
import org.wildfly.plugin.tools.DeploymentResult;
Expand All @@ -56,7 +56,7 @@
* @author <a href="mailto:[email protected]">James R. Perkins</a>
* @since 17-Nov-2010
*/
@SuppressWarnings({ "WeakerAccess", "TypeMayBeWeakened", "DeprecatedIsStillUsed", "deprecation", "unused" })
@SuppressWarnings({ "WeakerAccess", "TypeMayBeWeakened", "DeprecatedIsStillUsed", "unused" })
public class ArchiveDeployer {

private static final Logger log = Logger.getLogger(ArchiveDeployer.class);
Expand All @@ -77,8 +77,7 @@ public class ArchiveDeployer {
*/
@Deprecated
public ArchiveDeployer(DomainDeploymentManager deploymentManager) {
Assert.checkNotNullParam("deploymentManager", deploymentManager);
this.deploymentManagerDeprecated = deploymentManager;
this.deploymentManagerDeprecated = Objects.requireNonNull(deploymentManager, "The deploymentManager cannot be null");
this.deploymentManager = null;
}

Expand All @@ -88,7 +87,7 @@ public ArchiveDeployer(DomainDeploymentManager deploymentManager) {
* @param client the client used to communicate with the server
*/
public ArchiveDeployer(final ManagementClient client) {
Assert.checkNotNullParam("client", client);
Objects.requireNonNull(client, "The client cannot be null");
deploymentManagerDeprecated = null;
this.deploymentManager = DeploymentManager.Factory.create(client.getControllerClient());
}
Expand Down
8 changes: 4 additions & 4 deletions common/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@
<groupId>org.jboss.remotingjmx</groupId>
<artifactId>remoting-jmx</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.arquillian</groupId>
<artifactId>wildfly-testing-tools</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.core</groupId>
<artifactId>wildfly-controller-client</artifactId>
Expand All @@ -81,10 +85,6 @@
<groupId>org.jboss.shrinkwrap.descriptors</groupId>
<artifactId>shrinkwrap-descriptors-impl-base</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.common</groupId>
<artifactId>wildfly-common</artifactId>
</dependency>

<!-- Test dependencies -->
<dependency>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/*
* JBoss, Home of Professional Open Source.
*
* Copyright 2024 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.jboss.as.arquillian.container;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

import org.jboss.as.controller.client.ModelControllerClient;
import org.jboss.dmr.ModelNode;
import org.wildfly.plugin.tools.ContainerDescription;
import org.wildfly.plugin.tools.DeploymentManager;
import org.wildfly.plugin.tools.server.ServerManager;

/**
* A delegating implementation of a {@link ServerManager} which does not allow {@link #shutdown()} attempts. If either
* shutdown method is invoked, an {@link UnsupportedOperationException} will be thrown.
*
* @author <a href="mailto:[email protected]">James R. Perkins</a>
*/
class ArquillianServerManager implements ServerManager {

private final ServerManager delegate;

ArquillianServerManager(ServerManager delegate) {
this.delegate = delegate;
}

@Override
public ModelControllerClient client() {
return delegate.client();
}

@Override
public String serverState() {
return delegate.serverState();
}

@Override
public String launchType() {
return delegate.launchType();
}

@Override
public String takeSnapshot() throws IOException {
return delegate.takeSnapshot();
}

@Override
public ContainerDescription containerDescription() throws IOException {
return delegate.containerDescription();
}

@Override
public DeploymentManager deploymentManager() {
return delegate.deploymentManager();
}

@Override
public boolean isRunning() {
return delegate.isRunning();
}

@Override
public boolean waitFor(final long startupTimeout) throws InterruptedException {
return delegate.waitFor(startupTimeout);
}

@Override
public boolean waitFor(final long startupTimeout, final TimeUnit unit) throws InterruptedException {
return delegate.waitFor(startupTimeout, unit);
}

/**
* Throws an {@link UnsupportedOperationException} as the server is managed by Arquillian
*
* @throws UnsupportedOperationException as the server is managed by Arquillian
*/
@Override
public void shutdown() throws UnsupportedOperationException {
throw new UnsupportedOperationException("Cannot shutdown a server managed by Arquillian");
}

/**
* Throws an {@link UnsupportedOperationException} as the server is managed by Arquillian
*
* @throws UnsupportedOperationException s the server is managed by Arquillian
*/
@Override
public void shutdown(final long timeout) throws UnsupportedOperationException {
throw new UnsupportedOperationException("Cannot shutdown a server managed by Arquillian");
}

@Override
public void executeReload() throws IOException {
delegate.executeReload();
}

@Override
public void executeReload(final ModelNode reloadOp) throws IOException {
delegate.executeReload(reloadOp);
}

@Override
public void reloadIfRequired() throws IOException {
delegate.reloadIfRequired();
}

@Override
public void reloadIfRequired(final long timeout, final TimeUnit unit) throws IOException {
delegate.reloadIfRequired(timeout, unit);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.jboss.arquillian.container.test.spi.client.deployment.AuxiliaryArchiveAppender;
import org.jboss.as.arquillian.api.ServerSetup;
import org.jboss.as.arquillian.api.ServerSetupTask;
import org.jboss.as.arquillian.setup.ConfigureLoggingSetupTask;
import org.jboss.shrinkwrap.api.Archive;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.StringAsset;
Expand All @@ -42,6 +43,8 @@ public Archive<?> createAuxiliaryArchive() {
// shouldn't really be used for in-container tests.
.addClasses(ServerSetupTask.class, ServerSetup.class)
.addClasses(ManagementClient.class)
// Add the setup task implementations
.addPackage(ConfigureLoggingSetupTask.class.getPackage())
// Adds wildfly-plugin-tools, this exception itself is explicitly needed
.addPackages(true, OperationExecutionException.class.getPackage())
.setManifest(new StringAsset("Manifest-Version: 1.0\n"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ public void register(final ExtensionBuilder builder) {
builder.service(DeploymentExceptionTransformer.class, ExceptionTransformer.class);
builder.service(ResourceProvider.class, ArchiveDeployerProvider.class);
builder.service(ResourceProvider.class, ManagementClientProvider.class);
// Set up the providers for client injection of a ServerManager. We will not support injection for in-container
// tests. The main reason for this is we likely shouldn't be managing a servers lifecycle from a deployment. In
// some cases it may not even work.
builder.service(ResourceProvider.class, ServerManagerProvider.class);
builder.service(TestEnricher.class, ContainerResourceTestEnricher.class);
builder.service(AuxiliaryArchiveAppender.class, CommonContainerArchiveAppender.class);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@
import org.jboss.shrinkwrap.api.Archive;
import org.jboss.shrinkwrap.descriptor.api.Descriptor;
import org.wildfly.plugin.tools.ContainerDescription;
import org.wildfly.plugin.tools.server.ServerManager;
import org.wildfly.plugin.tools.server.StandaloneManager;

/**
* A JBossAS deployable container
Expand All @@ -72,6 +74,11 @@ public abstract class CommonDeployableContainer<T extends CommonContainerConfigu
@ApplicationScoped
private InstanceProducer<Context> jndiContext;

@Inject
@ContainerScoped
// Protected scope so the CommonManagedDeployableContainer can set it as well
protected InstanceProducer<ServerManager> serverManagerProducer;

private final StandaloneDelegateProvider mccProvider = new StandaloneDelegateProvider();
private ManagementClient managementClient = null;
private ContainerDescription containerDescription = null;
Expand Down Expand Up @@ -122,6 +129,18 @@ public final void start() throws LifecycleException {
}
mccProvider.setDelegate(ModelControllerClient.Factory.create(clientConfigBuilder.build()));

// If we are not a CommonManagedDeployableContainer we still need the ServerManager
if (!(this instanceof CommonManagedDeployableContainer)) {
// Set up the server manager attempting to discover the process for monitoring purposes. We need the
// server manager regardless of whether we are in charge of the lifecycle or not.
final StandaloneManager serverManager = ServerManager.builder()
.client(getManagementClient().getControllerClient())
// Note this won't work on Windows, but should work on other platforms
.process(ServerManager.findProcess().orElse(null))
.standalone();
serverManagerProducer.set(new ArquillianServerManager(serverManager));
}

try {
final Properties jndiProps = new Properties();
jndiProps.setProperty(Context.URL_PKG_PREFIXES, JBOSS_URL_PKG_PREFIX);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

import static org.wildfly.core.launcher.ProcessHelper.addShutdownHook;
import static org.wildfly.core.launcher.ProcessHelper.destroyProcess;
import static org.wildfly.core.launcher.ProcessHelper.processHasDied;

import java.io.IOException;
import java.io.InputStream;
Expand All @@ -33,6 +32,8 @@
import org.jboss.logging.Logger;
import org.wildfly.core.launcher.CommandBuilder;
import org.wildfly.core.launcher.Launcher;
import org.wildfly.plugin.tools.server.ServerManager;
import org.wildfly.plugin.tools.server.StandaloneManager;

/**
* A deployable container that manages a {@linkplain Process process}.
Expand All @@ -57,6 +58,13 @@ protected void startInternal() throws LifecycleException {
final T config = getContainerConfiguration();
if (isServerRunning(config)) {
if (config.isAllowConnectingToRunningServer()) {
// Set up the server manager attempting to discover the process for monitoring purposes. We need the
// server manager regardless of whether we are in charge of the lifecycle or not.
final StandaloneManager serverManager = ServerManager.builder()
.client(getManagementClient().getControllerClient())
.process(ServerManager.findProcess().orElse(null))
.standalone();
serverManagerProducer.set(new ArquillianServerManager(serverManager));
return;
} else {
failDueToRunning(config);
Expand All @@ -73,33 +81,19 @@ protected void startInternal() throws LifecycleException {
final Process process = Launcher.of(commandBuilder).setRedirectErrorStream(true).launch();
new Thread(new ConsoleConsumer(process, config.isOutputToConsole())).start();
shutdownThread = addShutdownHook(process);
final StandaloneManager serverManager = ServerManager.builder()
.client(getManagementClient().getControllerClient())
.process(process)
.standalone();

long startupTimeout = config.getStartupTimeoutInSeconds();
long timeout = startupTimeout * 1000;
boolean serverAvailable = false;
long sleep = 1000;
while (timeout > 0 && !serverAvailable) {
long before = System.currentTimeMillis();
serverAvailable = getManagementClient().isServerInRunningState();
timeout -= (System.currentTimeMillis() - before);
if (!serverAvailable) {
if (processHasDied(process)) {
final String msg = String.format(
"The java process starting the managed server exited unexpectedly with code [%d]",
process.exitValue());
throw new LifecycleException(msg);
}
Thread.sleep(sleep);
timeout -= sleep;
sleep = Math.max(sleep / 2, 100);
}
}
if (!serverAvailable) {
if (!serverManager.waitFor(startupTimeout, TimeUnit.SECONDS)) {
destroyProcess(process);
throw new TimeoutException(String.format("Managed server was not started within [%d] s", startupTimeout));
}
timeoutSupported = isOperationAttributeSupported("shutdown", "timeout");
this.process = process;
serverManagerProducer.set(new ArquillianServerManager(serverManager));

} catch (LifecycleException e) {
throw e;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.jboss.arquillian.core.api.annotation.Inject;
import org.jboss.arquillian.test.spi.TestEnricher;
import org.jboss.as.arquillian.api.ContainerResource;
import org.wildfly.plugin.tools.server.ServerManager;

/**
* Test enricher that allows for injection of remote JNDI context into @RunAsClient test cases.
Expand All @@ -51,6 +52,9 @@ public class ContainerResourceTestEnricher implements TestEnricher {
@Inject
private Instance<ManagementClient> managementClient;

@Inject
private Instance<ServerManager> serverManager;

/*
* (non-Javadoc)
*
Expand Down Expand Up @@ -123,6 +127,8 @@ private Object lookup(Class<?> type, ContainerResource resource, Annotation... q
return lookupContext(type, resource, qualifiers);
} else if (ManagementClient.class.isAssignableFrom(type)) {
return managementClient.get();
} else if (ServerManager.class.isAssignableFrom(type)) {
return serverManager.get();
} else {
throw new RuntimeException("@ContainerResource an unknown type " + resource.value());

Expand Down Expand Up @@ -177,8 +183,4 @@ private Annotation[] filterAnnotations(Annotation[] annotations) {
}
return filtered.toArray(new Annotation[0]);
}

private interface ContainerResourceProvider {
Object lookup(Class<?> type, ContainerResource resource, Annotation... qualifiers);
}
}
Loading

0 comments on commit 5d6d5df

Please sign in to comment.